由於DI的概念完全有意義,因此我最近用Dagger全身心地投入了工作。 DI的更好的「副產品」之一(就像傑克沃頓在他的演講中所說的那樣)是易於測試的。讓Dagger在爲Android做咖啡功能測試時注入模擬物體
所以現在我基本上使用espresso來做一些功能測試,並且我希望能夠嚮應用程序注入虛擬/模擬數據並讓活動顯示出來。我猜想,這是DI的最大優勢之一,這應該是一個相對簡單的問題。不過,出於某種原因,我似乎無法把頭圍住它。任何幫助將非常感激。這是我迄今(我已經寫了反映我的當前設置爲例):
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"
}
}
這些都是我的匕首模塊:
// 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;
}
// ...
}
在我的咖啡測試,我想插入模擬模塊,如下所示:
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"
}
}
}
這根本不起作用。我的咖啡測試運行,但TestNavigationModule完全被忽略... arr ... :(
我在做什麼錯了嗎?有沒有更好的方法來嘲笑模塊與咖啡出來我已經搜索和看到的例子Robolectric,使用等的Mockito但我只想純咖啡的測試和需要更換一個模塊與我的模擬一個我應該怎麼做這個
編輯:。。?
所以我決定用@ user3399328方法有一個靜態測試模塊列表定義,檢查null,然後將它添加到我的應用程序類。我仍然沒有得到我的測試注入版本的類,雖然我有一種感覺,但它可能是錯誤的用匕首測試模塊定義,而不是我的espresso生命週期。我做這個假設的原因是我添加了調試語句,並發現在應用程序類中注入靜態測試模塊時非空。你能否指出我可能做錯的方向?下面是我定義的代碼片段:
所有MyApplication:
@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;
}
}
這是要走的路。巧妙地繞過這個限制。先生們搖滾吧! –
當我嘗試在我的ActivityInstrumentationTestCase2子類的構造函數中注入我的測試模塊時,它不起作用,因爲應用程序已經實例化並且onCreate已被調用。所以我仍然沒有找到運行測試時聲明我的測試模塊的好方法 –
我目前正在嘗試@ user3399328的第二個解決方案(在我的測試源中提供另一版本的ActivityInjectHelper)。你有沒有找到一種方法讓它與Gradle一起工作?我一直在運行Android Studio中彈出的文件[文件名]錯誤中找到的重複類。 – Ben