在Dagger 2中测试模块和注射

时间:2016-01-30 09:33:11

标签: android dagger-2

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

我遇到的问题是在单位测试时间内更换模块。方案如下:

  • 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/下的类。到目前为止我所做的是将Component和模块复制并粘贴到/test/文件夹,并在那里进行注入的类声明。但我知道必须有一种正确的方法来实现我所寻找的目标。

我尝试的另一件事是使用自定义范围注释方法(创建@TestScope注释)。但是,这导致我遇到了之前评论过的相同问题:我无法使MyTest.class对组件可见,因为它位于/test/文件夹下。

我已经检查了其他类似的问题,例如this onethis another one,但最后一个问题是使用Robolectric运行测试,现在我已经能够仅使用JUnit4测试我的大部分代码(Android Studio 2-Beta 8)。

如果有人能指出我正确的方向,我会非常感激。

提前致谢!

1 个答案:

答案 0 :(得分:0)

您正在以一种仍然保持代码紧密耦合的方式使用依赖注入。一般来说,您希望您的依赖项是接口而不是实际的类。这使您的代码保持良好和松散,易于阅读,修改和维护。

隐藏界面背后的网络操作,以便您随时修改网络实施。这可以用于测试 - 在您的情况下,但如果您将来需要或不需要更改任何其他代码,它还允许您切换网络库。

尝试这样的事情:

@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的模拟版本并将其用于测试,无论是通过测试模块还是直接测试。