【发布时间】:2016-11-16 13:36:42
【问题描述】:
我最近在一个 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(){
//...
}
}
然后Component是这样的:
Singleton
@Component(modules={MyAppModule.class, NetworkModule.class})
public interface NetworkComponent {
//Activities that the providers can be injected into
void inject(MainActivity activity);
//...
}
对于我的测试,我使用的是 Robolectric,并且我的 Application 类有一个 Test 变体,如下所示:
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 模块的模拟版本,这些也被模拟,模拟的 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);
}
}
【问题讨论】:
-
您能在您的 TestNetworkModule 中添加什么吗?
-
当然,现在就在那里
-
你定义了当你的 picasso mock 被调用时应该发生什么?像这样:when(picassoMock.load(anyString())).thenReturn(something)
-
不,我还没有实现,我需要在每个测试中都这样做吗?
-
为什么在应用程序中使用单例? MyApplication.getInstance().getNetComponent().inject(this);您可以像这样访问您的 getNetComponent ((MyApplication) getApplication()).getNetComponent().inject(this);
标签: java android unit-testing robolectric dagger-2