Android 测试模块和Dagger 2中的注入
我目前正在开发一个Android MVP应用程序,我正试图在不同的Dagger2模块中分离我的依赖项 我遇到的问题是关于在单元测试时更改模块。情况如下:Android 测试模块和Dagger 2中的注入,android,dagger-2,Android,Dagger 2,我目前正在开发一个Android MVP应用程序,我正试图在不同的Dagger2模块中分离我的依赖项 我遇到的问题是关于在单元测试时更改模块。情况如下: @Singleton @Component(modules = {LoginModule.class, HTTPModule.class}) public interface LoginComponent { } @Module(includes = {HTTPModule.class}) public class LoginModule
@Singleton
@Component(modules = {LoginModule.class, HTTPModule.class})
public interface LoginComponent {
}
@Module(includes = {HTTPModule.class})
public class LoginModule {
@Provides
@Singleton
public MyThing provideMyThing(OkHttpClient client) {
// Do things with it
}
}
@Module
public class HTTPModule {
@Provides
@Singleton
public OkHttpClient provideOkHttpClient(){
// Return the OkHttpClient
}
}
- LoginComponent,它使用两个模块:LoginModule和HTTPModule
- LoginModule在其方法之一中需要一个OkHttp实例,该实例由HTTPModule提供
@Singleton
@Component(modules = {LoginModule.class, HTTPModule.class})
public interface LoginComponent {
}
@Module(includes = {HTTPModule.class})
public class LoginModule {
@Provides
@Singleton
public MyThing provideMyThing(OkHttpClient client) {
// Do things with it
}
}
@Module
public class HTTPModule {
@Provides
@Singleton
public OkHttpClient provideOkHttpClient(){
// Return the OkHttpClient
}
}
问题是,在测试时,我需要更改返回的OkHttpClient(通过让它接受所有证书,就像我在JVM上运行它时,它不接受LetsEncrypt证书一样)
我还需要它,因为我需要声明MyTest.class
可以注入模块,并且MyTest.class
位于app/src/test/
文件夹下,对于位于app/src/main/
下的类,它是不可见的。到目前为止,我所做的是将组件和模块复制并粘贴到/test/
文件夹中,并在那里进行注入类声明。但我知道一定有一个合适的方法来实现我所追求的
我尝试过的另一件事是用自定义范围对方法进行注释(创建@TestScope
注释)。但是,这导致了与我之前评论过的问题相同的问题:我无法使组件可见MyTest.class
,因为它位于/test/
文件夹下
我已经检查了其他类似的问题,例如和,但最后一个问题是用于使用Robolectric运行测试的,到目前为止,我只能使用JUnit4(Android Studio 2-Beta 8)对我的大部分代码进行单元测试
如果有人能给我指出正确的方向,我将不胜感激
提前谢谢 您使用依赖项注入的方式仍然使代码紧密耦合。一般来说,您希望依赖项是接口而不是实际的类。这使您的代码保持整洁、松散,易于阅读、修改和维护 将网络操作隐藏在接口后面,以便在需要时修改网络实现。在您的情况下,这可以用于测试,但如果您将来想或需要切换网络库,它还允许您在不更改任何其他代码的情况下切换网络库 试着这样做:
@Module
public class HTTPModule {
@Provides
@Singleton
public NetworkProvider provideNetworkProvider(){
// Return the Network provider
}
}
网络抽象层:
public interface NetworkProvider {
// Methods to send requests and receive async responses
}
OkHttp实现:
public class OkHttpNetworkProvider implements NetworkProvider {
// Implement NetworkProvider. This is the only class that
// knows about OkHttp and its components
}
现在,您可以创建一个模拟版的
NetworkProvider
,并使用它进行测试,无论是通过测试模块还是直接测试。有一篇文章是关于使用dagger进行测试的,可能会给您带来一些答案[link]在Dagger\uu component.builder()
的方法中创建组件时,您不能覆盖HTTPModule
@EpicPandaForce HTTPModule是一个模块,正如我所说,在Dagger 2中,似乎不支持对模块的方法重写,这是主要问题:(您可以重写模块的提供程序方法,只要您不在重写它的方法上指定@Provides
。如new HTTPModule(){@Override public provideOkHttpClient(){return new MockHttpClient();};
应该可以工作。谢谢你的回答,但这并不是我想要的。我想在这两种情况下都返回一个OkHttpClient,所以这里并不真正需要接口(除非你想添加另一层)。我遇到的问题是在测试时重写返回的实现。“还有一层”是不正确的,因为您没有网络层。OkHttp是一个特定的类。通过将其作为依赖项提供,您将您的多个类与OkHttp库紧密耦合,这是有代价的。无论哪种方式,您都可以使用mockito轻松创建它的模拟版本,并在实例化类进行测试时将其提供给您的类直接而不是通过模块