当前位置: 首页 > 工具软件 > AndroidJUnit4 > 使用案例 >

【Android】——单元测试、JUnit4、Mockito、Dagger2等

邹玮
2023-12-01

单元测试

单元测试,简称单测。测试一个类的一个方法是否能正常工作。
通常我们只对public方法进行测试。
测试可以理解为三部分:

  1. 创建这个类;
  2. 调用这个方法;
  3. 验证结果。

对于有返回值的方法,我们验证是否与预期值相同。
没有返回值的方法,我们要验证是否调用了该方法中的其他方法。(通过mock实现)

JUnit4

单测工具JUnit4常用注解

@Test

有这个注解,JUnit4就会当做是一个测试方法

@Before

在每个测试方法调用之前,调用这个方法

@After

每个测试方法运行结束之后,运行的方法

@BeforeClass

在所有测试方法之前,执行一次,且必须为static void

@AfterClass

在所有测试方法之后,执行一次,也必须为static void

一个JUnit4的单元测试用例执行顺序

@BeforeClass -> @Before -> @Test{方法A} -> @After -> @Before -> @Test{方法B} -> @After -> @AfterClass;

@Ignore

不运行这个测试方法

Assert类

Assert类用于验证结果。

Assert类中验证结果的方法

assertEquals(expected, actual)

验证expected的值跟actual是一样的,如果是一样的话,测试通过,不然的话,测试失败。(在比较object,用的是equals())

assertEquals(expected, actual, tolerance)

这里传入的expected和actual是float或double类型的,tolerance传入一个偏差值。如果两个数的差异在这个偏差值之内,则测试通过,否者测试失败。

assertTrue(boolean condition)

验证contidion的值是true

assertFalse(boolean condition)

验证contidion的值是false

assertNull(Object obj)

验证obj的值是null

assertNotNull(Object obj)

验证obj的值不是null

assertSame(expected, actual)

验证expected和actual是同一个对象,即指向同一个对象

assertNotSame(expected, actual)

验证expected和actual不是同一个对象,即指向不同的对象

fail()

让测试方法失败

Mockito

检验一个方法是否运行

void methodA()方法中,创建了ClassB对象,并且调用了ClassB对象的methodB()方法。我们通过检验methodB()方法是否执行来测试methodA()的结果:

@test
public void testMethodA() throws Exception{

    //通过Mockito.mock创建ClassB的对象,并传入我们要测试的methodA()
    ClassB mockClassBObject = Mockito.mock(ClassB.class)

    //......
    //创建ClassA,调用methodA,传入我们创建的mockClassAObject
    //......

    //检查结果
    Mockito.verify(mockClassBObject).methodB();
}

验证一个方法得到了多次调用:

Mockito.verify(mockClassBObject, Mockito.times(5)).methodB();

关于次数还有多种参数:atMost(count), atLeast(count), never()

不在乎参数的验证

Mockito.verify(mockClassBObject).methodB(Mockito.anyString(), Mockito.anyString());

这个方式表示任何参数都可以。同样的也有anyStringanyIntanyLonganyDouble,甚至anyCollection等。

指定一个方法的返回值

ClassC mockClassCObject = Mockto.mock(ClassC.class);

Mockito.when(mockClassCObject.methodC(params)).thenReturn(false);

当然也可以使用anything

Mockito.when(mockClassCObject.methodC(anything())).thenReturn(true);

指定某个对象的某个行为

public void methodA(String str1,String str2){   

    mClassBObject.methodB(str1 ,str2 ,new MyCallBack(){

        public void onFinish(String result){
        }

        public void onCancel(int code){
        }

    });
}

测试代码:
假设我们希望callback能返回onCancel(100)。

Mockito.doAnswer(new Answer(){

    @override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        //获取存放参数的数组arguments,我们可以通过它获得methodB方法参数
        Object[] arguments = invocation.getArguments();

        //因为源方法中callback是第三个参数,所以通过arguments[2]获取
        MyCallBack callBack = (MyCallBack)arguments[2];

        callBack.onCancel(100);
        return 100;

    }
}).when(mockClassBObject).methodB(anyString(),anyString(),any(MyCallBack.class));

Dagger2

依赖注入框架。
实现了通过ComponentModule找到Dependency提供给Client。

Module

Module类用@Module修饰
Module中,生产Dependency的方法用@Provides修饰

例子:

@Module
public Class MyModule(){
    @Provides
    public ParamClassA provideParamClassA(){
        //...根据需要创建了一个ParamClassA的对象,return出去
    }


    @Provides
    @Singleton  //这个标签可以方便的实现单例模式
    public ParamClassB provideParamClassB(){
        //...根据需要创建了一个ParamClassB的对象,return出去
    }

    @Provides
    public ClassC provideClassC(ParamClassA paraA,ParamClassB paraB){
        ClassC objectClassC = .....//通过paraA和paraB创建了objectClassC
    }
}

Component

Component接口的定义需要用 @Component修饰,并指定管理哪个Module
@Component(modules = {XXXModule.class})
(modules属性接收一个数组,里面是这个Component管理的所有Module。)
设置好后,Dagger2会为我们生成实现了这个XXComponent所有方法的DaggerXXComponent类。

@Component(modules = {MyModule.class})
interface MyComponent{
    ClassC classC();
}
public class MainActivity ...{

    private ClassC objectC;

    onCreate(){
    //...
    MyComponent mComponent = DaggerMyComponent.builder().MyModule(new MyModule().build();
    objectC = mComponent.classC();
    }
}

Field Injection

还可以写成更加简洁的Field Injection方式

修改上面的Component:

@Component(modules = {MyModule.class})
interface MyComponent{
    void inject(MainActivity mainActivity);
}

修改上面的Activity:

public class MainActivity ...{

    @Inject
    ClassC objectC;

    onCreate(){
    //...
    MyComponent mComponent = DaggerMyComponent.builder().MyModule(new MyModule().build();
    mComponent.inject(this);
    }
}

Robolectric

Robolectric实现了一套能在JVM运行的Android代码。
Robolectric实现Android里面的类的现有接口,也给每个Shadow类额外增加了很多接口。

 类似资料: