回页首 JMock 应用于 JUnit4 中
使用 JMock,项目需要导入 JMock 相关的一系列 Jar 包。我们可以通过 JMock 的官方网站得到这些 Jar 包。这样项目中就可以使用 JMock 的技术来辅助我们更好的完成单元测试了。
清单 1. 依赖其他类方法的类 TestJunit4.java
public class TestJunit4 {
private IMathfun util;
public TestJunit4(IMathfun util){
this.util = util;
}
public int cal(int num){
return 10* util.abs(num);
}
}
我们定义了一个很简单的类,在这个类中有 cal 方法,这个方法需要调用 IMathfun 接口中的 abs 方法。已知 cal 的作用就是对其参数取绝对值,然后再乘 10 返回。那么,cal 方法依赖于接口 IMathfun 的方法 abs 完成取绝对值,我们可以通过 Mock IMathfun 实例及方法来切断对其依赖性。
清单 2. 测试类 TestJunit4Test.java
1 public class TestJunit4Test extends TestCase{
2 private Mockery context = new JUnit4Mockery();
3 private IMathfun math = null;
4 private TestJunit4 test = null;
5 @Before
6 public void setUp() throws Exception {
7 super.setUp();
8 math = context.mock(IMathfun.class);
9 test = new TestJunit4(math);
10 context.checking(new Expectations(){
11 {
12 exactly(1).of(math).abs(-10);will(returnValue(10));
13 }
14 });
15 }
16 @After
17 public void tearDown() throws Exception {
18 }
19 @Test
20 public void test(){
21 assertEquals(100,test.cal(-10));
22 }
23}
写测试用例的过程也是对代码进行重新审查的过程,首先需要弄清楚待测的方法的功能是什么。其次多角度考虑这个方法该怎么写才是正确的、可靠的、高效的。再次,多考虑一些边界跟异常的情况。
通常 case 的数量是由参数的个数决定的。对于每一个参数,我们需要设计三种情况对其方法进行测试,即:为 null 值,正确值和错误值。这样如果方法有 n 个参数,那么理论上 case 的数量需要 3n个。这个数量所带来的工作量是非常大的,而且也是低效的。实际工作中,我们还需要另一个指标来衡量 case 的设计是否全面,那就是覆盖率。
Emma 是一个 Eclipse 的标准插件,通过这个工具我们可以得到类级别的语句覆盖率(statement coverage)和包级别的覆盖率(package coverage)。运行 Emma 后,工具会根据是否被执行将源代码行标注为不同的颜色,标记为红色的代码表示没有被执行,标记为绿色的代码表示已经被执行。我们可以通过以下步骤安装:
public class TestStatic{
public TestStatic(){}
public int getOSType(){
String os = Utils.getTargetOS();
if("Windows".equals(os))
Return 0;
else if("Linux".equals(os)||"Unix".equals(os))
Return 1;
else
Return 2;
}
}
public class Data {
private String name = "Na";
public String getName(){
return name;
}
private void setName(String str){
name = str;
}
}
Data类中的setName是私有方法。我们可以通过反射的方式对其测试。
清单 7. DataTest.java
public class DataTest extends TestCase{
@Before
public void setUp(){
}
@After
public void tearDown(){
}
@Test
public void test() throws Exception{
Data data = new Data();
System.out.println(data.getName());
Method m = data.getClass().getDeclaredMethod("setName", String.class);
m.setAccessible(true);
m.invoke(data, "Joh");
System.out.println(data.getName());
}
}
<!-- CMA ID: 656308 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-document-html-6.0.xsl --> 参考资料 学习
www.jmock.org/cookbook.htm:JMock 官方网站
http://www.junit.org:JUnit 官方网站
“让编译和测试过程自动化 Ant 和 JUnit 让您与 XP 梦想更近一步”(developerWorks,2001 年 10 月):逐步递增测试和持续编译是极端编程方法基础的两种。把两者合并成为一个单独的、自动进行的过程 — 加上自动生成电子邮件报告 — 您就将在向 XP 梦想前进的道路上迈出坚实的步子。请跟随 Erik Hatcher,他向您展示了他是如何修改流行的 Ant 1.3 和 JUnit 测试框架,以达到让编译和测试过程完全的、用户化的自动化。