- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我最近完全使用 Dagger,因为 DI 的概念完全有意义。 DI 的一个更好的“副产品”(正如 Jake Wharton 在他的一次演讲中所说)是更容易测试。
所以现在我基本上使用 Espresso 进行一些功能测试,并且我希望能够将虚拟/模拟数据注入(inject)应用程序并让 Activity 显示出来。我猜,这是 DI 的最大优势之一,这应该是一个相对简单的问题。但出于某种原因,我似乎无法绕过它。任何帮助将非常感激。到目前为止,这是我所拥有的(我写了一个反射(reflect)我当前设置的示例):
public class MyActivity
extends MyBaseActivity {
@Inject Navigator _navigator;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApplication.get(this).inject(this);
// ...
setupViews();
}
private void setupViews() {
myTextView.setText(getMyLabel());
}
public String getMyLabel() {
return _navigator.getSpecialText(); // "Special Text"
}
}
这些是我的 Dagger 模块:
// Navigation Module
@Module(library = true)
public class NavigationModule {
private Navigator _nav;
@Provides
@Singleton
Navigator provideANavigator() {
if (_nav == null) {
_nav = new Navigator();
}
return _nav;
}
}
// App level module
@Module(
includes = { SessionModule.class, NavigationModule.class },
injects = { MyApplication.class,
MyActivity.class,
// ...
})
public class App {
private final Context _appContext;
AppModule(Context appContext) {
_appContext = appContext;
}
// ...
}
在我的 Espresso 测试中,我试图插入一个模拟模块,如下所示:
public class MyActivityTest
extends ActivityInstrumentationTestCase2<MyActivity> {
public MyActivityTest() {
super(MyActivity.class);
}
@Override
public void setUp() throws Exception {
super.setUp();
ObjectGraph og = ((MyApplication) getActivity().getApplication()).getObjectGraph().plus(new TestNavigationModule());
og.inject(getActivity());
}
public void test_SeeSpecialText() {
onView(withId(R.id.my_text_view)).check(matches(withText(
"Special Dummy Text")));
}
@Module(includes = NavigationModule.class,
injects = { MyActivityTest.class, MyActivity.class },
overrides = true,
library = true)
static class TestNavigationModule {
@Provides
@Singleton
Navigator provideANavigator() {
return new DummyNavigator(); // that returns "Special Dummy Text"
}
}
}
这根本不起作用。我的 Espresso 测试运行了,但 TestNavigationModule 完全被忽略了... arr... :(
我做错了什么?有没有更好的方法来用 Espresso 模拟模块?我已经搜索并看到了使用 Robolectric、Mockito 等的示例。但我只想要纯 Espresso 测试,并且需要用我的模拟模块换掉一个模块。我该怎么做?
编辑:
所以我采用@user3399328 的方法来定义静态测试模块列表,检查是否为空,然后将其添加到我的应用程序类中。我仍然没有得到我的测试注入(inject)版本的类(class)。不过我有一种感觉,可能是 Dagger 测试模块定义有问题,而不是我的 Espresso 生命周期。我做出假设的原因是我添加了调试语句并发现静态测试模块在应用程序类中注入(inject)时是非空的。您能否指出我可能做错的方向。以下是我定义的代码 fragment :
我的应用程序:
@Override
public void onCreate() {
// ...
mObjectGraph = ObjectGraph.create(Modules.list(this));
// ...
}
模块:
public class Modules {
public static List<Object> _testModules = null;
public static Object[] list(MyApplication app) {
// return new Object[]{ new AppModule(app) };
List<Object> modules = new ArrayList<Object>();
modules.add(new AppModule(app));
if (_testModules == null) {
Log.d("No test modules");
} else {
Log.d("Test modules found");
}
if (_testModules != null) {
modules.addAll(_testModules);
}
return modules.toArray();
}
}
在我的测试类中修改了测试模块:
@Module(overrides = true, library = true)
public static class TestNavigationModule {
@Provides
@Singleton
Navigator provideANavigator()() {
Navigator navigator = new Navigator();
navigator.setSpecialText("Dummy Text");
return navigator;
}
}
最佳答案
有了 Dagger 2 和 Espresso 2,情况确实得到了改善。这就是测试用例现在的样子。请注意,ContributorsModel 由 Dagger 提供。此处提供完整演示:https://github.com/pmellaaho/RxApp
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {
ContributorsModel mModel;
@Singleton
@Component(modules = MockNetworkModule.class)
public interface MockNetworkComponent extends RxApp.NetworkComponent {
}
@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
MainActivity.class,
true, // initialTouchMode
false); // launchActivity.
@Before
public void setUp() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
RxApp app = (RxApp) instrumentation.getTargetContext()
.getApplicationContext();
MockNetworkComponent testComponent = DaggerMainActivityTest_MockNetworkComponent.builder()
.mockNetworkModule(new MockNetworkModule())
.build();
app.setComponent(testComponent);
mModel = testComponent.contributorsModel();
}
@Test
public void listWithTwoContributors() {
// GIVEN
List<Contributor> tmpList = new ArrayList<>();
tmpList.add(new Contributor("Jesse", 600));
tmpList.add(new Contributor("Jake", 200));
Observable<List<Contributor>> testObservable = Observable.just(tmpList);
Mockito.when(mModel.getContributors(anyString(), anyString()))
.thenReturn(testObservable);
// WHEN
mActivityRule.launchActivity(new Intent());
onView(withId(R.id.startBtn)).perform(click());
// THEN
onView(ViewMatchers.nthChildOf(withId(R.id.recyclerView), 0))
.check(matches(hasDescendant(withText("Jesse"))));
onView(ViewMatchers.nthChildOf(withId(R.id.recyclerView), 0))
.check(matches(hasDescendant(withText("600"))));
onView(ViewMatchers.nthChildOf(withId(R.id.recyclerView), 1))
.check(matches(hasDescendant(withText("Jake"))));
onView(ViewMatchers.nthChildOf(withId(R.id.recyclerView), 1))
.check(matches(hasDescendant(withText("200"))));
}
关于android - 在为 Android 进行 Espresso 功能测试时让 Dagger 注入(inject)模拟对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23233362/
Dagger 和 Dagger 2.0 有什么区别,为什么 Google 决定 fork 现有项目? 最佳答案 来自 Dagger 2 presentation 的一些引述 Dagger 1 的问题:
我想制作一个包含一个主要 Activity 和多个 fragment 的简单项目。在这里,我在一项 Activity 中有两个 fragment ,我想将演示者注入(inject)登录 fragmen
我是 dagger 的新手,我正在寻找如何在 dagger-2.x 中实现 spring 配置文件等功能。我想为我的开发环境和生产环境使用不同的 bean,但我使用的是带有 Java 的 Dagger
假设我有两个服务 AService 和 BService,它们都需要一个 API key 。 所以在我的模块中,我不能做类似的事情: @Provides @Singleton @A @ApiKey S
我对 Dagger 很陌生——我什至不知道它是否适用于我的应用程序 我有一个搜索页面,它返回有关给定名人的最新消息。 我写了一个测试来验证当我们搜索一个受欢迎的名人时结果会出现在页面上。 page有一
我最近将 dagger 2.8 更新为 2.9 dagger。和最新版本的文档已添加如下: -添加@BindsInstance组件构建器可以轻松绑定(bind)在图之外构建的实例。 -制作人:已添加
Dagger documentation页面说: To get the most out of compile-time validation, create a module that includ
我可以知道之间的区别吗? @Singleton VS 静态 在dagger2中提供? @Provides static User currentUser(AuthManager authManager
我有一个功能,我需要为不同的用户提供不同的房间数据库。 我正在使用 Dagger 2 创建房间数据库。我的应用程序组件创建一个房间数据库。当用户切换到另一个用户时,我想为此创建新的房间数据库,我需要创
我是 Dagger 2 的新手,正在尝试 IntelliJ 中的 Dagger 2 Coffee Example,它似乎不会生成 DaggerCoffeeApp_Coffee(它应该生成它),即使我密
我正在尝试在 Android 上使用 Dagger 2。我以前让它工作,我有一个 appModule 将依赖项注入(inject)应用程序中的特定类。我的问题是我收到错误 Error:(14, 55)
我是 kotlin 和 Dagger 的新手。我有一个小问题,我不知道如何解决,也没有找到解决方案。 这就是我所拥有的: @Module class AppModule (app: Applicati
我正在尝试使用 Dagger 建立一个项目。现在,当我构建时,没有为组件生成任何 Dagger* 类,并且出现以下错误: Error:(10, 8) error: [com.redditapp.dag
在 Dagger 中,我有时会看到有些组件只扩展一个接口(interface),而其他组件则使用 dependencies。 例如我们有一个基础组件: @Singleton @Component(mo
有没有办法告诉 Dagger 2 如何提供一些东西,但不允许它被注入(inject)? 假设我要注入(inject)一个 Qux .一个 Qux需要 Foo和 Bar : @Provides @Sin
( x-post from /r/androiddev ) 我只想在序言中说这不是一篇“哪个更好”的帖子;这严格来说是一个关于如何使用 Dagger 构建某些东西的问题(以及如何在 Kodein 中构
https://developer.android.com/topic/libraries/architecture/ 在Android架构蓝图中,为什么dagger是基于mvp架构而不是MVVM架构
我第一次开始同时使用 Kotlin 和 Dagger 2。我假设一切都与 Java 中的相同,但显然不完全相同。 Dagger 不会为我生成 Dagger* 文件。这是我的代码: 组件: @PerAc
我正在尝试将 Dagger 2 与 eclipse 集成,我使用的库如下: dagger-2.0.jar dagger-compiler-2.0.jar guava-13.0.1.jar javawr
我想练习这个Dagger 2 Vehicle Motor例子。 除了我的 gradel.build 之外,我所做的一切都与该教程中的一样: compile 'com.google.dagger:dag
我是一名优秀的程序员,十分优秀!