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测试可以使用不同参数多次运行同一个测试。

比如说测试斐波那契数列:

数列 值 F ( 0 ) 0 F ( 1 ) 1 F ( 2 ) 1 F ( 3 ) 2 F ( 4 ) 3 F ( 5 ) 5 F ( 6 ) 8 F ( n ) F ( n - 1 ) + F ( n - 2 )( n >= 2,n ∈ N*)

构造方法方式

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

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 早上上班忘记穿内衣了怎么办 高中知识都忘了怎么办 留鼻涕跟水一样怎么办 鼻涕像水一样流怎么办 肩膀很疼怎么办睡不着觉 夏天穿内衣出汗后很臭怎么办 脸过敏后严重缺水怎么办 过敏后脸上反复出现湿疹怎么办 孕妇脸上长湿疹过敏红肿怎么办 一岁宝宝一直流鼻涕怎么办 三岁宝宝一直流鼻涕怎么办 3岁宝宝一直流鼻涕不好怎么办 7岁半边鼻子不通气怎么办 感冒流鼻涕鼻子不通气怎么办 鼻子不通气干的怎么办 7个月婴儿流鼻涕怎么办 鼻子火辣辣的光想流鼻涕怎么办? 三岁宝宝鼻塞流鼻涕怎么办 一岁宝宝感冒流鼻涕鼻塞怎么办 1岁宝宝鼻塞流鼻涕怎么办 一岁多宝宝感冒鼻塞流鼻涕怎么办 宝宝鼻塞流鼻涕怎么办速效办法 八个月宝宝感冒流鼻涕鼻塞怎么办 7岁儿童流清鼻涕怎么办 1岁的宝宝流鼻涕怎么办 3岁宝宝鼻塞严重怎么办 宝宝流鼻涕2个月怎么办 一个月宝宝流鼻子怎么办 六个月宝宝流清水鼻涕怎么办 婴儿流鼻涕怎么办最简单方法 婴儿咳嗽流鼻涕怎么办最简单方法 6个月小孩流鼻涕怎么办 宝宝风寒感冒咳嗽流鼻涕怎么办 三个月宝宝流清鼻涕怎么办 三个月宝宝留清鼻涕怎么办 三个月婴儿流清鼻涕怎么办 宝宝7个月流鼻涕怎么办 6个月孩子流鼻涕怎么办 十一个月孩子感冒流鼻涕怎么办 7个月孩子流鼻涕怎么办 18个月的宝宝流鼻涕怎么办