单元测试 检验被测代码的一个有明确功能的小模块是否正确
白盒测试
开发人员是最大的受益者
// 组合测试
@RunWith(Suite.class)
@SuiteClasses({
V1AllTest.class.
V2AllTest.class
})
Assert.asserEquals()
Assert.assertTrue()
Assert.asserNotNull()
Assert.assertArrayEquals()
// 强制失败
Assert.fail();
@Test(expected = Ari…exception.class)
// 在当前类的测试方法之前或者之后执行
// 可以把测试方法之前的类对象new
@Before
public void setUp() {
}
@After
public void tearDown() {
}
// 在当前测试类之前或之后调用
@BeforeClass
public static void beforeClass(){
}
@AfterClass
public static void afterClass(){
}
单元测试有点
验证行为:
1.保证代码正确性
2.回归测试,项目后期可以去增加功能,修改程序结构而不用担心破坏重要gongn
3.给重构带来保证
设计行为
1.测试驱动 迫使我们从调用者角度去观察和思考问题,迫使我们把代码设计成可测试的,松耦合的
文档行为
1.单元测试时一种无价的文档,精确描述了代码的行为,是如何使用函数和类的最佳文档
原则
测试代码和被测代码同等重要,需要被同事维护
- 测试代码不是附属品,不但要重构代码也要重构单元测试
保持单元测试的简单性和可读性
单元测试一定是隔离的
测试用例运行结构不影响其他测试用例
测试用例不能互相依赖,可以乱序执行
单元测试一定可以重复
不能依赖环境变化(比如依赖时间或本机文件)
单元测试可以迅速执行
使用Mock对象对数据库,网络的依赖进行解耦
自动化单元测试
集成到build过程中去(可以验证功能是否正确)
使用Mock对象
真实对象不易构造
例如HttpServlet必须在Servlet容器才能创建
真实对象非常复杂
如JDBC中的Connection,ResultSet
真实对象的行为具有不确定性,难以控制他们的输出或者返回结果
真实对象有些行为难以触发,如硬盘已满,网络连接断开
真实对象可能还不存在,例如依赖的另外一个模块还没开发完成
TDD提供有力支持和对对象精确控制
MockObject的例子
HttpServletRequest 调用其中方法
方法1. 实现HttpServletRequest接口中的方法
EasyMock
// 录制和回放
// 创建mock对象
MockControl control = MockControl.createControl(HttpServletRequest.Class);
HttpServletRequest request = (HttpServletRequest )control.getMock();
// 设置并记录mock对象行为返回值
request.getParameter(“startRow”);
request.setReturnValue(“10”);
request.getParameter(“endRow”);
request.setReturnValue(“20”);
//转换成回放模式
control.replay();
// 测试代码
URLParser parser = new URLParser(request);
parser.parser()l;
Assert xxx;
对遗留代码进行测试
重构代码,提高可测试性
使用Mock Object解除依赖
测试分解
先写粗粒度的测试代码,然后编写细粒度的代码
Package -> class -> method
步骤
1.确定要测试的类和函数
2.解除依赖
3.编写测试用例
4.
将new 对象的依赖性语句做成一个单独保护方法
然后在测试中创建一个子类重写这个方法提一个Mock实现
public class Account{
public viod transfer() {
TransactionManager txManager = getManager();
}
protected TransactionManager getManager() {
return new TransactionManagerImpl();
}
}
// 测试
Account account = new Account() {
protected TransactionManager getManager() {
return new MockTransactionManager();
}
}
// 测试业务逻辑,Mock实现会被调用
account.transfer();
使用code coverage