我最近在一款Android应用程序中实现了Dagger2,以便进行轻松的依赖注入,但在这样做之后,我的部分测试已经停止工作。
现在我正在努力理解如何调整我的测试以适用于Dagger2?我正在使用Robolectric来运行我的测试。
以下是我使用Dagger2的方式,我最近才学会,所以这可能是不良习惯,而且并没有帮助测试,因此请指出我可以做出的任何改进。
我有一个AppModule,其内容如下:
@Module
public class MyAppModule {
//Application reference
Application mApplication;
//Set the application value
public MyAppModule(Application application) {
mApplication = application;
}
//Provide a singleton for injection
@Provides
@Singleton
Application providesApplication() {
return mApplication;
}
}
我所说的NetworkModule是提供注入对象的模块,具体如下:
@Module
public class NetworkModule {
private Context mContext;
//Constructor that takes in the required context and shared preferences objects
public NetworkModule(Context context){
mContext = context;
}
@Provides
@Singleton
SharedPreferences provideSharedPreferences(){
//...
}
@Provides @Singleton
OkHttpClient provideOKHttpClient(){
//...
}
@Provides @Singleton
Picasso providePicasso(){
//...
}
@Provides @Singleton
Gson provideGson(){
//...
}
}
然后这个组件就是这样的:
Singleton
@Component(modules={MyAppModule.class, NetworkModule.class})
public interface NetworkComponent {
//Activities that the providers can be injected into
void inject(MainActivity activity);
//...
}
在我的测试中,我使用Robolectric,并且我有一个测试变量的应用程序类,如下所示:
public class TestMyApplication extends TestApplication {
private static TestMyApplication sInstance;
private NetworkComponent mNetworkComponent;
@Override
public void onCreate() {
super.onCreate();
sInstance = this;
mNetworkComponent = DaggerTestMyApplication_TestNetworkComponent.builder()
.testMyAppModule(new TestMyAppModule(this))
.testNetworkModule(new TestNetworkModule(this)).build();
}
public static MyApplication getInstance() {
return sInstance;
}
@Override public NetworkComponent getNetComponent() {
return mNetworkComponent;
}
}
正如你所看到的,我正在努力确保使用模拟版本的Dagger2 Modules,这些也被模拟为使用模拟的MyAppModule返回TestMyApplication和模拟的NetworkModule返回模拟对象,我还有一个扩展真实NetworkComponent的模拟NetworkComponent。
在测试的设置中,我使用Robolectric创建Activity:
//Build activity using Robolectric
ActivityController<MainActivity> controller = Robolectric.buildActivity(MainActivity.class);
activity = controller.get();
controller.create(); //Create out Activity
这将创建Activity并启动onCreate方法,问题就出在这里,onCreate方法中我有以下代码来将Activity注入到组件中,以便它可以像这样使用Dagger2:
@Inject Picasso picasso; //Injected at top of Activity
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
MyApplication.getInstance().getNetComponent().inject(this);
picasso.load(url).fetch();
这里的问题是,当运行测试时,picasso变量会出现NullPointerException异常,因此我猜测我的Dagger2设置在测试中有遗漏的链接?
编辑:添加TestNetworkModule
@Module
public class TestNetworkModule {
public TestNetworkModule(Context context){
}
@Provides
@Singleton
SharedPreferences provideSharedPreferences(){
return Mockito.mock(SharedPreferences.class);
}
@Provides @Singleton
Gson provideGson(){
return Mockito.mock(Gson.class);
}
@Provides @Singleton
OkHttpClient provideOKHttpClient(){
return Mockito.mock(OkHttpClient.class);
}
@Provides @Singleton
Picasso providePicasso(){
return Mockito.mock(Picasso.class);
}
}