Java学习系列(二十五)基于Junit3.8和Junit4.x的单元测试详解
转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45281449
前言
好久没有写来CSDN写博客了,前段时间一直在加班赶项目,所以博客一直没有更新;现在空闲时间比较多,所以后面会长期更新博客。
今天来复习一下单元测试基于Junit工具的使用。Junit3.8与Junit4.x的使用还是有些区别的,所以分开来讲,但不管怎样,单元测试的目的并不是证明你是对的,而是为了证明你没有错误,同时也为提高程序健壮性、可重用测试、降低代码后期维护等提供了很好的支持和帮助。
(一) 基于Junit3.8的实例说明
/** * 基本四则运算 -- 目标类 * * @author [*昨日重现*] lhy_ycu@163.com * @since version 1.0 * @datetime 2015年4月24日 上午10:35:13 */ public class Calculator { private int add(int num1, int num2) { return num1 + num2; } public int subtract(int num1, int num2) { return num1 - num2; } public int multiply(int num1, int num2) { return num1 * num2; } public int divide(int num1, int num2) { if (num2 == 0) { throw new ArithmeticException("除数不能为0"); } return num1 / num2; } }
基于Junit3.8的测试类
/** * 基于Junit3.8 * * 测试源代码中的目标类,测试类必须继承TestCase * * @author [*昨日重现*] lhy_ycu@163.com * @since version 1.0 * @datetime 2015年4月24日 上午10:43:22 */ public class CalculatorTest extends TestCase { private Calculator cal = null; @Override protected void setUp() throws Exception { // TODO Auto-generated method stub super.setUp(); // 每个测试方法执行前,重新new一个对象,避免测试用例之间的依赖 cal = new Calculator(); System.out.println("在每个测试方法执行前执行--setUp..."); } /** * 测试源代码的私有方法 */ public void testAdd() { System.out.println("测试方法testAdd..."); // Assert.assertEquals(3, cal.add(1, 2));// blue bar try { // 1、getClass;2、Class.forName(); 3、.class Class<Calculator> calzz = Calculator.class; // Class<?> calzz = Class.forName("com.leo.junit.Calculator"); // Calculator cal = calzz.newInstance(); Method method = calzz.getDeclaredMethod("add", new Class[] { Integer.TYPE, Integer.TYPE });// 后两个参数为:方法名、参数类型 method.setAccessible(true);// 设置为可访问私有的add方法 // 后两个参数为:目标类对象、实参对象;返回目标方法的结果 Object obj = method.invoke(cal, new Object[] { 1, 2 }); Assert.assertEquals(3, obj); } catch (Exception e) { // e.printStackTrace(); Assert.fail(); } } public void testSubstrub() { System.out.println("测试方法testSubstrub..."); Assert.assertEquals(3, cal.subtract(1, 2));// red bar,failure 说明测试没有通过(失败) } public void testMultiply() { System.out.println("测试方法testMultiply..."); Assert.assertEquals(2, cal.multiply(1, 2));// blue bar } public void testDivide() { System.out.println("测试方法testDivide..."); Assert.assertEquals(2, cal.divide(1, 0));// red bar, error 说明测试程序本身出错 } @Override protected void tearDown() throws Exception { // TODO Auto-generated method stub super.tearDown(); // cal = null;// 在每个测试方法执行后主动销毁对象 System.out.println("在每个测试方法执行后执行--tearDown...\n"); } // public static void main(String[] args) { // junit.textui.TestRunner.run(CalculatorTest.class);// 控制台打印错误日志 // } }
注意事项:
1)Junit的原则:keep the bar green to keep the code clean。2)测试类与(源代码)目标类的包名尽量要一致,最终它们都会被编译到同一个目录下面,这样就不用导入源代码所在的包。
3) 测试类的命名规则:测试类类名 = 目标类类名前或后加Test; 注意要统一。
4) 测试类必须继承TestCase; 测试用例(方法/类)与测试用例之间一定是完全独立的,不允许出现任何的依赖关系。同时也不能依赖测试方法的执行顺序,也就是删除或注释掉某个测试方法后,其他的测试方法依然能够执行。
5) 测试源代码的私有方法可以采取两种方式:1、修改目标方法的访问修饰符(将private修改为public,一般不推荐);2、使用反射在测试类中调用目标类的私有方法。
(二)基于Junit4.x的实例说明
/** * 基于Junit4.X --主要基于注解Annotation * * @author [*昨日重现*] lhy_ycu@163.com * @since version 1.0 * @datetime 2015年4月25日 上午12:06:52 */ // @Ignore 将忽略掉该类的所有测试方法 public class CalculatorTest2 { private Calculator cal = null; @BeforeClass public static void beforeClass() { System.out.println("=========在所有测试方法执行前执行--beforeClass=====\n"); } /** * 在测试方法执行完前执行 */ @Before public void beforeMethod() { System.out.println("在每个测试方法执行前执行--beforeMethod..."); cal = new Calculator(); } // 若超时1s,将报error错误 @Test(timeout = 1000) // 若期待有异常抛出:expected = Exception.class public void testSubstrub() // throws Exception { System.out.println("测试方法testSubstrub被执行..."); Assert.assertEquals(-1, cal.subtract(1, 2)); // Assert.assertEquals(-1, cal.divide(1, 0)); } @Test @Ignore("该testMultiply测试方法由于XX原因需要被忽略掉") public void testMultiply() { System.out.println("测试方法testMultiply被执行..."); Assert.assertEquals(2, cal.multiply(1, 2)); } /** * assertThat及Hamcrest的基本使用 */ @Test public void testOther() { int result = cal.subtract(1, 2); // 关于字符串 String s1 = "leo"; org.junit.Assert.assertThat(result, Matchers.is(-1)); org.junit.Assert.assertThat(s1, Matchers.not("llleo")); // org.junit.Assert.assertThat(s1, Matchers.equalToIgnoringCase("LeO")); // org.junit.Assert.assertThat(s1, // Matchers.equalToIgnoringWhiteSpace(" Leo ")); // org.junit.Assert.assertThat(s1, Matchers.containsString("leo")); // org.junit.Assert.assertThat(s1, Matchers.startsWith("le")); // org.junit.Assert.assertThat(s1, Matchers.endsWith("o")); // org.junit.Assert.assertThat(s1, Matchers.equalTo("leo")); // 关于基本类型 double d1 = 3.1; // 在3.0±0.2之间 org.junit.Assert.assertThat(d1, Matchers.closeTo(3.0, 0.2)); // 大于3.0 org.junit.Assert.assertThat(d1, Matchers.greaterThan(3.0)); // 小于4.0 org.junit.Assert.assertThat(d1, Matchers.lessThan(4.0)); // 大于或等于3.0 org.junit.Assert.assertThat(d1, Matchers.greaterThanOrEqualTo(3.0)); // 小于或等于4.0 org.junit.Assert.assertThat(d1, Matchers.lessThanOrEqualTo(4.0)); // 关于集合 Map<String, String> map = new HashMap<String, String>(); map.put("k1", "zhangsan"); map.put("k2", "lisi"); // 是否含有该k1=zhangsan的键值对 org.junit.Assert.assertThat(map, Matchers.hasEntry("k1", "zhangsan")); // 是否含有键为k2的Item org.junit.Assert.assertThat(map, Matchers.hasKey("k2")); // 是否含有值为lisi的Item org.junit.Assert.assertThat(map, Matchers.hasValue("lisi")); } /** * 在测试方法执行完后执行 */ @After public void afterMethod() { // cal = null;// 在每个测试方法执行后主动销毁对象 System.out.println("在每个测试方法执行后执行--afterMethod...\n"); } @AfterClass public static void afterClass() { System.out.println("=========在所有测试方法执行后执行--afterClass====="); } }
注意事项:
1)在一个测试类中,所有被@Test注解所修饰的public void方法都是测试用例,可以被JUnit所执行。
2) failure是指测试失败,而error是指测试程序本身出错。
结束语
明天开始续《Java学习系列》,包括反射、注解、内部类等等。