更新时间:2023-01-23 17:19:42
我已经远远做到了这一点(我不能完全肯定这将规模尚)是在我的测试中创建一个静态测试模块类。
@Module(
注射= {
共享preferences.class
}) 静态类TestModule {
@Provides @Singleton共享preferences provideShared preferences(){
返回Mockito.mock(共享preferences.class);
}
}
和在设置()方法我注入测试模块
@Before
公共无效设置(){
。ObjectGraph.create(新TestModule())注入(本);
}
然后我@Inject嘲笑类:
@Inject共享preferences共享preferences;
I have a Gradle app with a project structure similar to Jake Wharton's u2020:
/src
/androidTest
/debug
/main
/release
In my application class I build the Dagger graph and inject it:
MyApplication extends Application {
...
public void buildObjectGraphAndInject() {
Object[] modules = Modules.list(this);
mApplicationGraph = ObjectGraph.create(modules);
mApplicationGraph.inject(this);
}
...
}
Inside the debug sourceset, I define Modules.list()
as:
public final class Modules {
public static Object[] list(MyApplication app) {
return new Object[] {
new AppModule(app),
new DebugAppModule()
};
}
private Modules() {
// No instances.
}
}
Inside the release sourceset, I define the same thing minus the DebugAppModule:
public final class Modules {
public static Object[] list(MyApplication app) {
return new Object[] {
new AppModule(app)
};
}
private Modules() {
// No instances.
}
}
Deeper down my dependency graph, I create a MockRestAdapter that I can use when running the debug version:
@Module(
complete = false,
library = true,
overrides = true
)
public final class DebugApiModule {
@Provides @Singleton Endpoint provideEndpoint(@ApiEndpoint StringPreference apiEndpoint) {
return Endpoints.newFixedEndpoint(apiEndpoint.get());
}
@Provides @Singleton MockRestAdapter provideMockRestAdapter(RestAdapter restAdapter, SharedPreferences preferences) {
MockRestAdapter mockRestAdapter = MockRestAdapter.from(restAdapter);
AndroidMockValuePersistence.install(mockRestAdapter, preferences);
return mockRestAdapter;
}
@Provides @Singleton MyApi provideMyApi(RestAdapter restAdapter, MockRestAdapter mockRestAdapter,
@IsMockMode boolean isMockMode, MockMyApi mockService) {
if (isMockMode) {
return mockRestAdapter.create(MyApi.class, mockService);
}
return restAdapter.create(MyApi.class);
}
}
But while I'm running tests, I would like to override the DebugApiModule with a TestApiModule that looks like this:
@Module(
complete = false,
library = true,
overrides = true
)
public final class TestApiModule {
@Provides @Singleton Endpoint provideEndpoint(@ApiEndpoint StringPreference apiEndpoint) {
return Endpoints.newFixedEndpoint(apiEndpoint.get());
}
@Provides @Singleton MockRestAdapter provideMockRestAdapter(RestAdapter restAdapter, SharedPreferences preferences) {
MockRestAdapter mockRestAdapter = MockRestAdapter.from(restAdapter);
mockRestAdapter.setDelay(0);
mockRestAdapter.setErrorPercentage(0);
mockRestAdapter.setVariancePercentage(0);
return mockRestAdapter;
}
@Provides @Singleton MyApi provideMyApi(MockRestAdapter mockRestAdapter, MockHnApi mockService) {
return mockRestAdapter.create(MyApi.class, mockService);
}
}
What's the best way to accomplish this? Do I need to create a TestAppModule
like this:
public final class Modules {
public static Object[] list(MyApplication app) {
return new Object[] {
new AppModule(app),
new TestAppModule()
};
}
private Modules() {
// No instances.
}
}
And replace all of the DebugFooModule
with TestFooModules
? If so, how do I get around the fact that Modules.java
is duplicated? Or am I way off base?
EDIT: SOLUTION
What I ended up doing is replacing the Application-level graph (where the MockRestAdapter gets created) during my test setUp
protected void setUp() throws Exception {
super.setUp();
HnApp app = HnApp.getInstance();
app.buildObjectGraphAndInject(TestModules.list(app));
getActivity();
}
What I've done this far (and I'm not entirely sure this will scale yet) is create a static test module class in my tests.
@Module(
injects = {
SharedPreferences.class
})
static class TestModule {
@Provides @Singleton SharedPreferences provideSharedPreferences(){
return Mockito.mock(SharedPreferences.class);
}
}
And in the setup() method I inject the test module
@Before
public void setUp(){
ObjectGraph.create(new TestModule()).inject(this);
}
I then @Inject the mocked class:
@Inject SharedPreferences sharedPreferences;