既然前文提到依赖注入使得程序易于测试,那么使用了dagger2框架的程序怎么进行测试?怎么测试,具体来讲有很多问题,尤其安卓下的测试。这里主要介绍一下和dagger2框架相关的一些东西。
首先,第一个问题,什么是单元测试?为什么依赖注入使得程序便于单元测试?
关于这个问题,stackexchange上有一个很好的讨论,从多个角度讨论了这个问题。 点击打开链接
第一点:从定义上说,如果测试的类中有其它的依赖,那么它就是一个集成测试/功能测试,而非单元测试。
第二点:单元测试和集成测试都是为了找出bug,只是在有了单元测试的情况下,集成测试更加容易debug。这个其实很好理解,如果你有一个Widget类,依赖于AAA类,BBB类,然后你发现Widget类中有一个方法有bug,这时候你很难说是Widget类的代码,还是AAA,BBB类中的代码引起的bug。所以,使用了依赖注入的程序可以注入一些mock的依赖来确保在某一个测试中,你可以把精力集中到Widget类本身,而不是它的依赖(AAA、BBB类)。
然后,第二个问题,安卓下面怎么用dagger2注入mock的依赖? 安卓开发大神Chiu已经给出很好的方案。
点击打开链接
点击打开链接
方案1
第一步:build.gradle中配置test support library/mockito/espresso
第二步:在管理控制着依赖注入的注入者的类(多是Application类)中暴露setCompoment方法
第三步:在安卓instrument测试包下建立测试类,通过注释设置AndroidJUnit4 Runner :@RunWith(AndroidJUnit4.class)
第四步:在安卓instrument测试包下建立测试用的mock Module,指明注入mock类的来源。当然是用Mockito,返回Mockito.mock()。
第五步:在测试类中添加注入接口,在前一篇文章里说过,一个被注入的类需要一个inject()方法,现在需要注入到测试类中,自然需要添加inject()方法。如何添加,定义一个内部接口,继承自原来的注入接口,并且添加一个inject方法。
第六步:在setup方法里注入依赖,在测试方法中mock这个注入依赖的行为。
Chiu大神认为这个方案不是很优雅,因为她认为Application类中的setCompoment方法似乎是专门测试用的,而产品代码中不应该有专用于测试的代码。我个人认为好像是有点过于苛刻了,这是一个标准的setter方法么,无非是产品代码中可能不太会使用这个方法,也不能说这个方法就是专门用于测试的吧。以后再回过头来看这个观点吧。
方案2
Chiu大神认为这个方案比较好。
第一步:同上配置gradle
第二步:同方案1,第三步设置注入源。
第三步:在安卓instrument测试包下建立application类,继承主程序中的application类,重写获取component的方法,使得这个application里的注入依赖是Mockito mock的
第四步:自定义runner,在安卓instrument测试包下继承AndroidJUnitRunner类,重写newApplication方法,传入测试包中的application类。可想而知,这一步的目的就是在测试的时候,用测试包下的application类替换主程序的application类。
第五步:gradle中指明使用新的runner
具体代码可参考
https://github.com/nanyi5452/cleanDemo