Junit4
来源:互联网 发布:华为揽阅m2青春版改mac 编辑:程序博客网 时间:2024/06/05 19:04
Junit4
https://github.com/junit-team/junit4/wiki
断言
Junit提供了重载的原生类型、对象、数组(原生类型或对象)断言方法。参数的顺序是期待值和实际值。或者第一个参数可以是当测试失败的时候输出一个String类型的错误消息。有一个稍微不同的断言assertThat,assertThat参数为一个可选的错误消息,实际值和一个Matcher对象。注意 assertThat期待值与实际值的顺序与其他断言方法相反。
每个断言方法表示如下:
import static org.hamcrest.CoreMatchers.allOf;import static org.hamcrest.CoreMatchers.anyOf;import static org.hamcrest.CoreMatchers.both;import static org.hamcrest.CoreMatchers.containsString;import static org.hamcrest.CoreMatchers.equalTo;import static org.hamcrest.CoreMatchers.everyItem;import static org.hamcrest.CoreMatchers.hasItems;import static org.hamcrest.CoreMatchers.not;import static org.hamcrest.CoreMatchers.sameInstance;import static org.hamcrest.CoreMatchers.startsWith;import static org.junit.Assert.assertArrayEquals;import static org.junit.Assert.assertEquals;import static org.junit.Assert.assertFalse;import static org.junit.Assert.assertNotNull;import static org.junit.Assert.assertNotSame;import static org.junit.Assert.assertNull;import static org.junit.Assert.assertSame;import static org.junit.Assert.assertThat;import static org.junit.Assert.assertTrue;import java.util.Arrays;import org.hamcrest.core.CombinableMatcher;import org.junit.Test;public class AssertTests { @Test public void testAssertArrayEquals() { byte[] expected = "trial".getBytes(); byte[] actual = "trial".getBytes(); assertArrayEquals("failure - byte arrays not same", expected, actual); } @Test public void testAssertEquals() { assertEquals("failure - strings are not equal", "text", "text"); } @Test public void testAssertFalse() { assertFalse("failure - should be false", false); } @Test public void testAssertNotNull() { assertNotNull("should not be null", new Object()); } @Test public void testAssertNotSame() { assertNotSame("should not be same Object", new Object(), new Object()); } @Test public void testAssertNull() { assertNull("should be null", null); } @Test public void testAssertSame() { Integer aNumber = Integer.valueOf(768); assertSame("should be same", aNumber, aNumber); } // JUnit Matchers assertThat @Test public void testAssertThatBothContainsString() { assertThat("albumen", both(containsString("a")).and(containsString("b"))); } @Test public void testAssertThatHasItems() { assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three")); } @Test public void testAssertThatEveryItemContainsString() { assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n"))); } // Core Hamcrest Matchers with assertThat @Test public void testAssertThatHamcrestCoreMatchers() { assertThat("good", allOf(equalTo("good"), startsWith("good"))); assertThat("good", not(allOf(equalTo("bad"), equalTo("good")))); assertThat("good", anyOf(equalTo("bad"), equalTo("good"))); assertThat(7, not(CombinableMatcher.<Integer> either(equalTo(3)).or(equalTo(4)))); assertThat(new Object(), not(sameInstance(new Object()))); } @Test public void testAssertTrue() { assertTrue("failure - should be true", true); }}
测试 fixtures
有四个fixture注解:两个用于类级别的fixture,另外两个用于方法级别的fixture。 在类级别,有@BeforeClass和@AfterClass,在方法(或测试)级别,有@Before和@After。
package test;import java.io.Closeable;import java.io.IOException;import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;public class TestFixturesExample { static class ExpensiveManagedResource implements Closeable { @Override public void close() throws IOException {} } static class ManagedResource implements Closeable { @Override public void close() throws IOException {} } @BeforeClass public static void setUpClass() { System.out.println("@BeforeClass setUpClass"); myExpensiveManagedResource = new ExpensiveManagedResource(); } @AfterClass public static void tearDownClass() throws IOException { System.out.println("@AfterClass tearDownClass"); myExpensiveManagedResource.close(); myExpensiveManagedResource = null; } private ManagedResource myManagedResource; private static ExpensiveManagedResource myExpensiveManagedResource; private void println(String string) { System.out.println(string); } @Before public void setUp() { this.println("@Before setUp"); this.myManagedResource = new ManagedResource(); } @After public void tearDown() throws IOException { this.println("@After tearDown"); this.myManagedResource.close(); this.myManagedResource = null; } @Test public void test1() { this.println("@Test test1()"); } @Test public void test2() { this.println("@Test test2()"); }}
输出如下:
@BeforeClass setUpClass@Before setUp@Test test2()@After tearDown@Before setUp@Test test1()@After tearDown@AfterClass tearDownClass
测试执行顺序
按照设计,Junit没有指定测试方法调用的执行顺序。到目前为止,方法只是按照反射API返回的顺序进行调用。但是,使用JVM命令是不明智的,因为Java平台没有指定任何特定的顺序,实际上JDK 7返回或多或少的随机顺序。当然,精心编写的测试代码不会做任何顺序的假设,但有些则需要,在某个特定的平台上一个可预测的测试失败要好与随机的测试失败。
从4.11版开始,JUnit将默认使用确定性但不可预测的顺序(MethodSorters.DEFAULT)。要更改测试执行顺序,只需使用@FixMethodOrder对测试类进行注明,并指定一个可用的MethodSorters:
@FixMethodOrder(MethodSorters.JVM):按照JVM返回的顺序执行测试方法。这个顺序每次运行可能都不一样。
@FixMethodOrder(MethodSorters.NAME_ASCENDING):按照字典顺序对测试方法名排序。
import org.junit.FixMethodOrder;import org.junit.Test;import org.junit.runners.MethodSorters;@FixMethodOrder(MethodSorters.NAME_ASCENDING)public class TestMethodOrder { @Test public void testA() { System.out.println("first"); } @Test public void testB() { System.out.println("second"); } @Test public void testC() { System.out.println("third"); }}
以上代码会按照测试方法名的升序顺序执行
Suite聚合测试
使用Suite做为Runner允许我们手动创建一个包含其他类的suite。同JUnit 3.8.x 的static Test suite()方法一样。使用Suite,需要在类上使用注解@RunWith(Suite.class) 和 @SuiteClasses(TestClass1.class, …)。当你运行这个类的时候,它会运行suite中所有类的测试。
下面的类注明了suite注解,并且不需要其他实现。注意@RunWith注解,它指定使用JUnit 4测试Runner,org.junit.runners.Suite来运行这个特定的测试类。他需要与@Suite注解一起使用,@Suite告诉Suite Runner包含的测试类和顺序。
import org.junit.runner.RunWith;import org.junit.runners.Suite;@RunWith(Suite.class)@Suite.SuiteClasses({ TestFeatureLogin.class, TestFeatureLogout.class, TestFeatureNavigate.class, TestFeatureUpdate.class})public class FeatureTestSuite { // the class remains empty, // used only as a holder for the above annotations}
忽略测试
如果由于某些原因,你不希望测试失败,你只想忽略它,你可以暂时禁用一个测试。
要忽略JUnit中的测试,你可以将方法注释掉,或者删除@Test注解; 但测试Runner不会报告这样的测试。 或者,你可以在@Test之前或之后添加@Ignore注解。 测试Runner将报告忽略测试的数量,以及运行的测试数量和失败的测试数量。
注意,如果要记录测试被忽略的原因,可以使用@Ignore的可选参数(一个字符串)
@Ignore("Test is ignored as a demonstration")@Testpublic void testSame() { assertThat(1, is(1));}
期望异常
你是如何验证代码是否按期望抛出异常? 验证代码正常完成很重要,但确保代码在特殊情况下按预期运行也至关重要。 例如:
new ArrayList<Object>().get(0);
该代码应该抛出一个IndexOutOfBoundsException。 @Test注解有一个可选参数“expected”,它作为Throwable的子类。 如果我们想验证ArrayList抛出正确的异常,我们会写:
@Test(expected = IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); }
应小心使用expected参数。 如果方法中的任何代码抛出IndexOutOfBoundsException异常,上述测试将通过。 对于较长的测试,建议使用如下描述的ExpectedException规则。
上述方法对简单的情况是有用的,但它也有其局限性。 例如,不能测试异常的消息值,或者异常抛出后域对象的状态。
Try/Catch
为了解决这个问题,你可以使用JUnit 3.x中的try / catch:
@Testpublic void testExceptionMessage() { try { new ArrayList<Object>().get(0); fail("Expected an IndexOutOfBoundsException to be thrown"); } catch (IndexOutOfBoundsException anIndexOutOfBoundsException) { assertThat(anIndexOutOfBoundsException.getMessage(), is("Index: 0, Size: 0")); }}
期望异常规则
或者,使用ExpectedException规则。 此规则可以让你不仅指出你期望的是什么异常,还可以指出你期望的异常消息
@Rulepublic ExpectedException thrown = ExpectedException.none();@Testpublic 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}
期望消息还可以使用Matchers,这可以让你在测试中有更大的灵活性,例如:
thrown.expectMessage(Matchers.containsString("Size: 0"));
此外,可以你可以使用Matchers来检查异常,如果它具有要验证的嵌入状态,那么它将非常有用。例如:
import static org.hamcrest.Matchers.hasProperty;import static org.hamcrest.Matchers.is;import static org.hamcrest.Matchers.startsWith;import javax.ws.rs.NotFoundException;import javax.ws.rs.core.Response;import javax.ws.rs.core.Response.Status;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(NotFoundException.class); thrown.expectMessage(startsWith("some Message")); thrown.expect(hasProperty("response", hasProperty("status", is(404)))); testThing.chuck(); } private class TestThing { public void chuck() { Response response = Response.status(Status.NOT_FOUND).entity("Resource not found").build(); throw new NotFoundException("some Message", response); } }}
有关ExpectedException规则的延伸讨论,请参阅此博文。
测试超时
如果一个测试“失控”或花费太长时间,可能会自动失败。有两种可选方法可以实现此行为
在@Test注解上使用超时参数(应用于测试方法)
您可以选择以毫秒为单位指定超时,以使测试方法在超过该毫秒数的时间内失败。 如果超出时间限制,则会因为抛出异常而触发测试失败:
@Test(timeout=1000)public void testWithTimeout() { ...}
超时规则(应用于测试类的所有测试用例)
超时规则对类中的所有测试方法应用相同的超时
import org.junit.Rule;import org.junit.Test;import org.junit.rules.Timeout;public class HasGlobalTimeout { public static String log; private final CountDownLatch latch = new CountDownLatch(1); @Rule public Timeout globalTimeout = Timeout.seconds(10); // 10 seconds max per method tested @Test public void testSleepForTooLong() throws Exception { log += "ran1"; TimeUnit.SECONDS.sleep(100); // sleep for 100 seconds } @Test public void testBlockForever() throws Exception { log += "ran2"; latch.await(); // will block }}
Matchers and assertthat
Joe Walnes在JMock 1之上建立了一个新的断言机制。方法名称是assertThat,语法如下所示:
assertThat(x, is(3));assertThat(x, is(not(4)));assertThat(responseString, either(containsString("color")).or(containsString("colour")));assertThat(myList, hasItem("3"));
通用语法:
assertThat([value], [matcher statement]);
此断言语法的优点包括:
更可读和可分类:
这种语法允许你根据主语,动词,对象(assert“x is 3”)来考虑
而不是assertEquals,它使用动词,对象,主语(assert“等于3 x”)
组合:Matchers语句可以是
否定(not(s))
组合((either(s).or(t))
映射到集合(each(s))
或者使用自定义组合(afterFiveSeconds(s))
比较:
assertTrue(responseString.contains("color") || responseString.contains("colour"));// ==> failure message: // java.lang.AssertionError:assertThat(responseString, anyOf(containsString("color"), containsString("colour")));// ==> failure message:// java.lang.AssertionError: // Expected: (a string containing "color" or a string containing "colour")// got: "Please choose a font"
更多Matchers参考:Matchers
Parameterized
Parameterized测试可以使用不同参数多次运行同一个测试。
比如说测试斐波那契数列:
构造方法方式
import static org.junit.Assert.assertEquals;import java.util.Arrays;import java.util.Collection;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.Parameterized;import org.junit.runners.Parameterized.Parameters;@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() { //fInput = 0,fExpected = 0 测试1次 //fInput = 1,fExpected = 1 测试1次 //fInput = 2,fExpected = 1 测试1次 //依次类推,一共测试 6 次 assertEquals(fExpected, Fibonacci.compute(fInput)); }}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; }}
属性注入方式
当前只能用于public属性
import static org.junit.Assert.assertEquals;import java.util.Arrays;import java.util.Collection;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.Parameterized;import org.junit.runners.Parameterized.Parameter;import org.junit.runners.Parameterized.Parameters;@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 } }); } @Parameter // first data value (0) is default public /* NOT private */ int fInput; @Parameter(1) public /* NOT private */ int fExpected; @Test public void test() { assertEquals(fExpected, Fibonacci.compute(fInput)); }}public class Fibonacci { ...}
Rule
Rule允许在测试类中非常灵活地添加或重新定义每个测试方法的行为。 测试人员可以重复使用或扩展以Rule,也可以自行编写。
测试方法名规则
TestName Rule 可以在测试方法中使用当前测试方法名:
public class NameRuleTest { @Rule public final TestName name = new TestName(); @Test public void testA() { // name.getMethodName() 会获取当前测试方法名 assertEquals("testA", name.getMethodName()); } @Test public void testB() { assertEquals("testB", name.getMethodName()); }}
超时规则
Timeout Rule 对类中的所有测试方法应用相同的超时时间
public static class HasGlobalTimeout { public static String log; @Rule public final TestRule globalTimeout = Timeout.millis(20); @Test public void testInfiniteLoop1() { // 死循环,肯定会超时,报TestTimedOutException异常 log += "ran1"; for(;;) {} } @Test public void testInfiniteLoop2() { log += "ran2"; for(;;) {} }}
异常规则
ExpectedException Rules 允许对预期的异常类型和消息进行测试
public static class HasExpectedException { @Rule public final ExpectedException thrown = ExpectedException.none(); @Test public void throwsNothing() { } @Test public void throwsNullPointerException() { thrown.expect(NullPointerException.class); throw new NullPointerException(); } @Test public void throwsNullPointerExceptionWithMessage() { thrown.expect(NullPointerException.class); thrown.expectMessage("happened?"); thrown.expectMessage(startsWith("What")); throw new NullPointerException("What happened?"); }}
更多Rule或者自定义Rule参考 https://github.com/junit-team/junit4/wiki/Rules
- JUnit4
- JUnit4
- junit4
- junit4
- JUnit4
- junit4
- JUnit4
- JUNIT4
- Junit4
- JUnit4
- junit4
- Junit4
- Junit4
- Junit4
- JUnit4
- JUnit4
- junit4
- JUnit4
- ccff打酱油
- 从零开始前端学习[33]:Cs3中的transition过渡-animation动画
- HDU
- bootstrap table样式丢失
- Mac系统 QuickTime 屏幕录制
- Junit4
- Mybatis简单的操作数据库
- cmd下ftp传送文件显示553Permission denied.
- A Cubic number and A Cubic Number
- 线程的概念
- 并查集应用总结 内置例题
- 学习Linux C编程 strlen及unsigned问题
- Maven讲解之 仓库
- python爬虫网页解析中的疑难杂症...