Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 测试模块和Dagger 2中的注入_Android_Dagger 2 - Fatal编程技术网

Android 测试模块和Dagger 2中的注入

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

我目前正在开发一个Android MVP应用程序,我正试图在不同的Dagger2模块中分离我的依赖项

我遇到的问题是关于在单元测试时更改模块。情况如下:

@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轻松创建它的模拟版本,并在实例化类进行测试时将其提供给您的类直接而不是通过模块