单元测试,简称单测。测试一个类的一个方法是否能正常工作。
通常我们只对public方法进行测试。
测试可以理解为三部分:
对于有返回值的方法,我们验证是否与预期值相同。
没有返回值的方法,我们要验证是否调用了该方法中的其他方法。(通过mock实现)
有这个注解,JUnit4就会当做是一个测试方法
在每个测试方法调用之前,调用这个方法
每个测试方法运行结束之后,运行的方法
在所有测试方法之前,执行一次,且必须为static void
在所有测试方法之后,执行一次,也必须为static void
@BeforeClass -> @Before -> @Test{方法A} -> @After -> @Before -> @Test{方法B} -> @After -> @AfterClass;
不运行这个测试方法
Assert类用于验证结果。
验证expected的值跟actual是一样的,如果是一样的话,测试通过,不然的话,测试失败。(在比较object,用的是equals())
这里传入的expected和actual是float或double类型的,tolerance传入一个偏差值。如果两个数的差异在这个偏差值之内,则测试通过,否者测试失败。
验证contidion的值是true
验证contidion的值是false
验证obj的值是null
验证obj的值不是null
验证expected和actual是同一个对象,即指向同一个对象
验证expected和actual不是同一个对象,即指向不同的对象
让测试方法失败
在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());
这个方式表示任何参数都可以。同样的也有anyString,anyInt,anyLong,anyDouble,甚至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));
依赖注入框架。
实现了通过Component从Module找到Dependency提供给Client。
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修饰,并指定管理哪个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方式
修改上面的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实现了一套能在JVM运行的Android代码。
Robolectric实现Android里面的类的现有接口,也给每个Shadow类额外增加了很多接口。