单元测试和集成测试
- 单元测试:侧重于忽略外部组件的情况下,测试代码的正确性,因此单元测试下需要自行mock数据。
- 集成测试:侧重于测试各个组件配合使用下,各组件是否正常运行。
在Spring test中,已经提供了集成测试功能,本文章给大家简单介绍下阿里巴巴的单测框架testable,但它每次执行测试用例时都需要重新加载容器,运行速度很慢,在某些情况下,可能我们只需要mock依赖的component即可,而不需要完整的spring容器,此时就可以使用testable。
Testable框架简介
单元测试中的Mock方法,通常是为了绕开那些依赖外部资源或无关功能的方法调用,使得测试重点能够集中在需要验证和保障的代码逻辑上。
在定义Mock方法时,开发者真正关心的只有一件事:“这个调用,在测试的时候要换成那个假的Mock方法”。
当下主流的Mock框架在实现Mock功能时,需要开发者操心的事情实在太多:Mock框架如何初始化、与所用的服务框架是否兼容、要被Mock的方法是不是私有的、是不是静态的、被Mock对象是new出来的还是注入的、怎样把被测对象送回被测类里…这些非关键的额外工作极大分散了使用Mock工具应有的乐趣。
而Testable框架实现了快速mock任意方法,减少负担。
使用方式
构造任意对象
该框架提供了一种方式构造任意对象,如果对象中存在子对象也会相应的去做初始化,而不是简单的赋空值。
// 构造一个WhatEverClass类型的对象
WhatEverClass obj = OmniConstructor.newInstance(WhatEverClass.class);
// 构造一个WhatEverClass[]类型,容量为5的数组
WhatEverClass[] arr = OmniConstructor.newArray(WhatEverClass.class, 5);
// 使用构造函数创建对象
Parent parent = new Parent();
// 内部成员未初始化,直接访问报NullPointerException异常(❌)
parent.getChild().getGrandChild();
// 使用OmniConstructor创建对象
Parent parent = OmniConstructor.newInstance(Parent.class);
// 无需顾虑,安心访问任意子成员(✅)
parent.getChild().getGrandChild().getContent();
mock任意方法
首先为测试类添加一个关联的Mock类型,作为承载其Mock方法的容器,最简单的做法是在测试类里添加一个名称为Mock的静态内部类。例如:
public class DemoTest {
public static class Mock {
// 放置Mock方法的地方
// 原方法签名为`String substring(int, int)`
// 调用此方法的对象`"something"`类型为`String`
@MockInvoke(targetClass = String.class)
private String substring(int i, int j) {
return "sub_string";
}
// 当遇到待覆写方法有重名时,可以将需覆写的方法名写到@MockInvoke注解的targetMethod参数里,这样Mock方法自身就可以随意命名了。
// 使用`targetMethod`指定需Mock的方法名
// 此方法本身现在可以随意命名,但方法参数依然需要遵循相同的匹配规则
@MockInvoke(targetClass = String.class, targetMethod = "substring")
private String use_any_mock_method_name(int i, int j) {
return "sub_string";
}
}
}