单元测试编写原则及如何使用jmockit

   通常在写单元测试时,最好以测试人员的身份进行编写,这样有利于早期的bug发现及代码重构。一般单元测试以业务场景为基础。每个场景单独进行测试,根据预测结果与实际返回值进行比对,得出程序功能是否正确。
  

费话不多说,直接上代码。以下描述一个完整的例子,以Junit 4为基础
1.类及方法
public class StockActionTest {
	/**
         *描述本用例的业务场所景
	 */
	@Test
	public void testGetSomething(){
StockActionTest类并不一定以Test结尾或开头,只是一种约定,Junit 4里面只要对方法进行@Test注解即可告诉测试框架需要测试该方法,而Junit 3中类需要继承TestCase,并且测试方法以test开头。

2.初始化、资源释放及回收
	/**
	 * 用例执行前的初始化等操作
	 * @throws Exception
	 */
	@Before
	public void setUp() throws Exception {
                initData();
		mockMethod();
	}

	/**
	 * 用例执行完毕后资源释放等操作
	 * @throws Exception
	 */
	@After
	public void tearDown() throws Exception {
		Mockit.tearDownMocks();
	}
以上两个方法均服务于每个测试方法,会在方法前和方法后执行,我们可以把初始化数据或者mock方法写在此处,另外方法执行完毕也可以写tearDown方法进行相关的释放。当然要视情况而定,如果资源初始化以后不会变的,可以写在@BeforeClass方法里面。

3.方法断言
//执行结果判断
StockAction sa = new StockAction();
QueryResult result = sa.getShift(motivation, "7", "021H", "1200");
//编码为021H02
Assert.assertEquals("021R1400", result.getBatchCode());
//工作日是周天
Assert.assertEquals("7", result.getTime());

这是最重要的一步,断言实际功能的返回值与预期的是否相同,Junit提供了assertEquals、assertTrue、assertFalse等方法。

4.如何mock
当程序中遇到第三方接口,数据库连接,文件读写等与业务逻辑不相干因素时,我们就得借助mock工具。在使用mock之前,我们还是有解决办法的。比如三方接口的场景。我们可以实现三方接口,但这样会造成实现类中很多空实现的方法,另外由于要查看三方的实现源码逻辑,会比较耗时。所以想到了mock工具。
Mock工具这里首选jmockit,因为该工具即能mock接口,也能mock静态方法,final方法等,这是其它工具jmock,easymock,mockito不能比拟的。

//要测试的类,该类里面引用了IMatcher三方接口
StockConnectorImpl sc

//通过Mocked关键字指定会生成代理matcher对象
@Mocked
IMatcher matcher;

private void mockMethod(){
    //将代理对象注入到测试类实例
    sc = new StockConnectorImpl(matcher);
    
    new MockUp<IMatcher>(){
    //mock代理对象的接口方法,返回你所想到要值
        @Mock
	public List<T> getSomething(String code){
		//doSomething
        }

    }.getMockInstance();
}

通过MockUp的匿名类生成代理对象的方法,运行时会执行里面的方法。
Jmockit还可以mock测试类本身的方法,当然不建议那样做。

new Expectations(sc){
{
	Deencapsulation.invoke(sc, "getBatchIds","021H");
	Set<String> result = new HashSet<String>();
	result.add("593406263");
	returns (result);
	}
};
另Expectations
的方式也可以进行mock,这种方法就其实是运用了反射

Mockit.tearDownMocks();

最后做还原动作, 确保用例之间不相互影响。

@RunWith(Suite.class)
@Suite.SuiteClasses({StockActionTest.class})
public class RouteTestAll {
	
}

添加StockActionTest到测试套,以便可以执行多个测试用例。后续新用例,只用往StockActionTest.class添加。

结合Coverage插件,可以更清楚的了解代码编写的质量。

你可能感兴趣的:(jmock)