单元测试这一块咱们一直都有在接触,可是对于我来讲,还不够重视或深刻,能够说是忽视的一块,如今公司要把测试覆盖率给推起来,此时正好能够来探究探究。 JUnit4 单元测试主要有如下的一些功能:html
注意:本版本基于JUnit4.12。java
下面咱们会对这样的一个类作参数测试,咱们需呀一个 参数 和 一个预期结果值git
public class Fibonacci { public static int compute(int n) { int result = 0; if (n <= 1) { result = n; } else { result = compute(n - 1) + compute(n - 2); } return result; } }
如何作测试?第一个方法是构造函数方式github
@RunWith(Parameterized.class) public class FibonacciTest { @Parameters public static Collection<Object[]> data() { /* 数组第一个 为 参数, 第二个为 指望结果 */ return Arrays.asList(new Object[][] {{0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}}); } private int fInput; private int fExpected; public FibonacciTest(int input, int expected) { fInput = input; fExpected = expected; } @Test public void test() { Assert.assertEquals(fExpected, Fibonacci.compute(fInput)); } }
非构造函数实现(推荐:非构造函数更加灵活,不会影响类的其余方法):数组
@RunWith(Parameterized.class) public class FibonacciTest2 { @Parameters public static Collection<Object[]> data() { return Arrays.asList(new Object[][] {{0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}}); } @Parameter // first data value (0) is default public /* NOT private */ int fInput; // 数组第一个参数为输入参数 @Parameter(1) public /* NOT private */ int fExpected; // 数组第一个参数为 预期参数 @Test public void test() { Assert.assertEquals(fExpected, Fibonacci.compute(fInput)); } }
参考:https://github.com/junit-team/junit4/wiki/Parameterized-tests函数
在咱们编写测试用例的过程当中,咱们每每都会有指望异常的测试方法,有异常就是对了。 举一个例子单元测试
new ArrayList<Object>().get(0);
这样的方法毫无疑问会爆出IndexOutOfBoundsException 数组越界异常,为此,咱们要验证这个异常的出现是正确的,咱们能够@Test(exceted=IndexOutOfBoundsException.class) 来标记指望的异常。测试
@Test(expected = IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); }
然而这个只是方法之一,但却不是推荐的方法,对于更长的测试,建议使用ExpectedException Rule 来实现;ui
对异常进行更深的测试: 上面的方式是一个很是好的示例,可是他是有限制的。例如, 不能在异常中测试消息的值, 也不能在引起异常后检测域对象的状态。在Junit3.x 是用 try/catch 来作的(这个不浪费时间叙述),可是在Junit4.x 可使用 @Rule 来实现。使用 ExpectedException 规则。此规则容许您不只指示所指望的异常, 并且还能够显示所指望的异常消息。 实现以下:this
public class TestExyRule { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void shouldTestExceptionMessage() throws IndexOutOfBoundsException { List<Object> list = new ArrayList<Object>(); thrown.expect(IndexOutOfBoundsException.class); thrown.expectMessage("Index: 0, Size: 0"); list.get(0); // execution will never get past this line } }
上面例子的expectMessage 可使用 Matchers 来作, 这样能够更加的灵活,如:thrown.expectMessage(Matchers.containsString("Size: 0")); 固然咱们也能够更加进一步的 验证异常的状态:
import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; public class TestExy { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void shouldThrow() { TestThing testThing = new TestThing(); thrown.expect(UnsupportedOperationException.class); thrown.expectMessage(startsWith("some Message")); testThing.chuck(); } private class TestThing { public void chuck() { throw new UnsupportedOperationException("some Message"); } } }
https://github.com/junit-team/junit4/wiki/Exception-testing
https://github.com/junit-team/junit4/wiki/Timeout-for-tests 超时测试比较简单,举个例子。
@Test(timeout =1000) public void testMethod() { for(;;){} }
如上面的代码咱们对时间作了限制为1s, 可是因为有死循环,是没法在规定时间内经过测试的。
https://github.com/junit-team/junit4/wiki/Aggregating-tests-in-suites
https://github.com/junit-team/junit4/wiki/Categories