首页 > 其他 > 详细

Junit 4

时间:2015-10-27 23:49:50      阅读:303      评论:0      收藏:0      [点我收藏+]

【转】Junit4详解一:Junit总体介绍

转自http://www.cnblogs.com/caoyuanzhanlang/p/3534846.html

    Junit是一个可编写重复测试的简单框架,是基于Xunit架构的单元测试框架的实例。Junit4最大的改进是大量使用注解(元数据),很多实际执行 过程都在Junit的后台做完了,而且写test case 的类不需要继承TestCase,只需要在所要做test case的方法前加@Test 注解即可。

如:

技术分享
技术分享
1 import static org.junit.Assert.*;
2 2 public class TestCaculatorClass {
3 3     @Test
4 4     public void test() throws IOException, RuntimeException{
5 5         CaculatorClassForTest cal = new CaculatorClassForTest();
6 6         assertEquals(30, cal.sum(10, 20));
7 7     }
8 8 }
技术分享

直接点击右键,run as... Junit Test即可运行此test case。

Assert类里面有很多assert方法,包括:assertEquals(), assertNotNull(),assertTtrue(),assertFalse(),assertThat()等,其中assertThat用的是match的形式。

因此,Junit提供很多中Match,其中CoreMatchers是其中一个比较完善的实现类。具体有上面方法可以查阅CoreMatchers类。

技术分享
技术分享
 1 import static org.hamcrest.CoreMatchers.allOf;
 2 import static org.hamcrest.CoreMatchers.anyOf;
 3 import static org.hamcrest.CoreMatchers.equalTo;
 4 import static org.hamcrest.CoreMatchers.not;
 5 import static org.hamcrest.CoreMatchers.sameInstance;
 6 import static org.hamcrest.CoreMatchers.startsWith;
 7 import static org.junit.Assert.assertThat;
 8 import static org.junit.matchers.JUnitMatchers.both;
 9 import static org.junit.matchers.JUnitMatchers.containsString;
10 import static org.junit.matchers.JUnitMatchers.everyItem;
11 import static org.junit.matchers.JUnitMatchers.hasItems;
12 
13 import java.util.Arrays;
14 
15 import org.hamcrest.core.CombinableMatcher;
16 import org.junit.Test;
17 
18 public class AssertTests {
19   @Test
20   public void testAssertArrayEquals() {
21     byte[] expected = "trial".getBytes();
22     byte[] actual = "trial".getBytes();
23     org.junit.Assert.assertArrayEquals("failure - byte arrays not same", expected, actual);
24   }
25 
26   @Test
27   public void testAssertEquals() {
28     org.junit.Assert.assertEquals("failure - strings not same", 5l, 5l);
29   }
30 
31   @Test
32   public void testAssertFalse() {
33     org.junit.Assert.assertFalse("failure - should be false", false);
34   }
35 
36   @Test
37   public void testAssertNotNull() {
38     org.junit.Assert.assertNotNull("should not be null", new Object());
39   }
40 
41   @Test
42   public void testAssertNotSame() {
43     org.junit.Assert.assertNotSame("should not be same Object", new Object(), new Object());
44   }
45 
46   @Test
47   public void testAssertNull() {
48     org.junit.Assert.assertNull("should be null", null);
49   }
50 
51   @Test
52   public void testAssertSame() {
53     Integer aNumber = Integer.valueOf(768);
54     org.junit.Assert.assertSame("should be same", aNumber, aNumber);
55   }
56 
57   // JUnit Matchers assertThat
58   @Test
59   public void testAssertThatBothContainsString() {
60     org.junit.Assert.assertThat("albumen", both(containsString("a")).and(containsString("b")));
61   }
62 
63   @Test
64   public void testAssertThathasItemsContainsString() {
65     org.junit.Assert.assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));
66   }
67 
68   @Test
69   public void testAssertThatEveryItemContainsString() {
70     org.junit.Assert.assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n")));
71   }
72 
73   // Core Hamcrest Matchers with assertThat
74   @Test
75   public void testAssertThatHamcrestCoreMatchers() {
76     assertThat("good", allOf(equalTo("good"), startsWith("good")));
77     assertThat("good", not(allOf(equalTo("bad"), equalTo("good"))));
78     assertThat("good", anyOf(equalTo("bad"), equalTo("good")));
79     assertThat(7, not(CombinableMatcher.<Integer> either(equalTo(3)).or(equalTo(4))));
80     assertThat(new Object(), not(sameInstance(new Object())));
81   }
82 
83   @Test
84   public void testAssertTrue() {
85     org.junit.Assert.assertTrue("failure - should be true", true);
86   }
87 }
技术分享

问题一,我可不可以把多个测试类放在一起执行?

回答: 可以。org.junit.runner.JUnitCore.runClasses(TestClass1.class, ...);利用这样,把test case 的类放进去,然后放在main()方法里执行。

问题二,@RunWith这个注解有什么作用?

回答:Junit4的默认runner为BlockJunit4ClassRunner,但是Junit4包括第三方软件还提供很多其他的runner,这样如果,我们想让我们的测试类用专门的runner来运行,这时候就可以用@RunWith(Suit.class

)标注测试类。其他特殊的runner有:

1. Suite: 字面理解是一个套装,通俗地讲,就是你可以把很多测试类放在一起,然后建一个类,标注为Suite.class,那么如果执行这个类,就会把所有的测试类一起执行。

技术分享
技术分享
 1 import org.junit.runner.RunWith;
 2 import org.junit.runners.Suite;
 3 
 4 @RunWith(Suite.class)
 5 @Suite.SuiteClasses({
 6   TestFeatureLogin.class,
 7   TestFeatureLogout.class,
 8   TestFeatureNavigate.class,
 9   TestFeatureUpdate.class
10 })
11 
12 public class FeatureTestSuite {
13   // the class remains empty,
14   // used only as a holder for the above annotations
15 }
技术分享

 

2. Parameterized:根据所设计的参数来执行测试。假设我们要测试某一个方法,它有两个参数,每个参数需要设计不同值,那么我们最开始就是需要为 每个参数设计一个测试方法,这样就很麻烦,10种case就得10个方法,但是有了Parameterized runner,我们可以设计一个方法,多种参数来执行test case。

技术分享
技术分享
 1 package com.citi.risk.core.test.impl;
 2 
 3 public class CaculatorClassForTest {
 4     
 5     private int o1;
 6     private int o2;
 7     public int getO1() {
 8         return this.o1;
 9     }
10     public void setO1(int value) {
11         this.o1 = value;
12     }
13     public int getO2() {
14         return this.o2;
15     }
16     public void setO2(int value) {
17         this.o2 = value;
18     }
19     
20     
21     public CaculatorClassForTest() {}
22     public CaculatorClassForTest(int o1, int o2) {
23         this.o1 = o1;
24         this.o2 = o2;
25     }
26     
27     public int sum(int o1, int o2){
28         if(o1 > 200) {
29             throw new RuntimeException("o1 is too big");
30         }
31         if(o2 > 200) {
32             throw new RuntimeException("o2 is too big");
33         }
34         int sum;
35         sum = o1 + o2;
36         return sum;
37     }
38 }
技术分享

 

 

技术分享
技术分享
 1 package com.citi.risk.core.test.impl;
 2 
 3 import static org.junit.Assert.*;
 4 
 5 import java.io.IOException;
 6 import java.util.List;
 7 
 8 import org.junit.Rule;
 9 import org.junit.Test;
10 import org.junit.rules.ExpectedException;
11 import org.junit.runner.RunWith;
12 import org.junit.runners.Parameterized;
13 import org.junit.runners.Parameterized.Parameter;
14 import org.junit.runners.Parameterized.Parameters;
15 
16 import com.google.common.collect.Lists;
17 
18 @RunWith(Parameterized.class)
19 public class TestCaculatorClass {
20     @Rule
21     public ExpectedException thrown = ExpectedException.none();
22     
23     @Parameters
24     public static List<Object[]> data() {
25         return Lists.asList(new Object[]{-1, 1, 0}, new Object[][]{{20, 20, 40},{30, 30, 60},{-5, -5, -10}});
26     }
27     @Parameter(value = 0)
28     public int o1;
29     @Parameter(value = 1)
30     public int o2;
31     @Parameter(value = 2)
32     public int expector;
33     
34     @Test
35     public void test() throws IOException, RuntimeException{
36         CaculatorClassForTest cal = new CaculatorClassForTest();
37         assertEquals(expector, cal.sum(o1, o2));
38     }
39     
40     @Test
41     public void testO1Exception(){
42         CaculatorClassForTest cal = new CaculatorClassForTest();
43         thrown.expect(RuntimeException.class);
44         thrown.expectMessage("o1 is too big");
45         cal.sum(300, 100);
46     }
47     @Test
48     public void testO2Exception(){
49         CaculatorClassForTest cal = new CaculatorClassForTest();
50         thrown.expect(RuntimeException.class);
51         thrown.expectMessage("o2 is too big");
52         cal.sum(100, 300);
53     }
54     
55 }
技术分享

 

 以上两个类就是测试了Parameterized runner, 参数会自动匹配。它其实就是,看我们传入几种case, 也就是List.size(),然后,把类里面的方法,循环重复执行size()数目。

3. Categories:容易理解就是分类执行。假设我们有一种case: 我们写好了两个测试类,类A,类B,A有两个方法a(), b(),这时候我们有一个类来执行这两个类的test case,但是我们在类A里只想执行A.b(),但却不执行A.a(),这个时候我们可以用Categories runner。

技术分享
技术分享
 1 public interface FastTests { /* category marker */ }
 2 public interface SlowTests { /* category marker */ }
 3 
 4 public class A {
 5   @Test
 6   public void a() {
 7     fail();
 8   }
 9 
10   @Category(SlowTests.class)
11   @Test
12   public void b() {
13   }
14 }
15 
16 @Category({SlowTests.class, FastTests.class})
17 public class B {
18   @Test
19   public void c() {
20 
21   }
22 }
23 
24 @RunWith(Categories.class)
25 @IncludeCategory(SlowTests.class)
26 @SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
27 public class SlowTestSuite {
28   // Will run A.b and B.c, but not A.a
29 }
30 
31 @RunWith(Categories.class)
32 @IncludeCategory(SlowTests.class)
33 @ExcludeCategory(FastTests.class)
34 @SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
35 public class SlowTestSuite {
36   // Will run A.b, but not A.a or B.c
37 }
技术分享
 

4. Enclosed:如果我们把tests放在了内部类,这时候执行外部类是无法执行里面的test cases,这种情况下,就应该在outer class 用Enclosed runner。

要测试的类 Address:

技术分享
技术分享
 1 package abstractions.domain;
 2 
 3     import java.io.Serializable;
 4 
 5     import com.google.common.collect.ComparisonChain;
 6 
 7     public class Address implements Serializable, Comparable<Address> {
 8 
 9         private static final long serialVersionUID = 1L;
10         private final String address1;
11         private final String city;
12         private final String state;
13         private final String zip;
14 
15         private Address(Builder builder) {
16             this.address1 = builder.address1;
17             this.city = builder.city;
18             this.state = builder.state;
19             this.zip = builder.zip;
20         }
21 
22         public String getAddress1() {
23             return address1;
24         }
25 
26         public String getCity() {
27             return city;
28         }
29 
30         public String getState() {
31             return state;
32         }
33 
34         public String getZip() {
35             return zip;
36         }
37 
38         @Override
39         public int compareTo(Address that) {
40             return ComparisonChain.start().compare(this.zip, that.zip).compare(this.state, that.state)
41                     .compare(this.city, that.city).compare(this.address1, that.address1).result();
42         }
43 
44         @Override
45         public boolean equals(Object obj) {
46             if (obj == null) { return false; }
47             if (getClass() != obj.getClass()) { return false; }
48             final Address that = (Address) obj;
49 
50             return com.google.common.base.Objects.equal(this.address1, that.address1)
51                     && com.google.common.base.Objects.equal(this.city, that.city)
52                     && com.google.common.base.Objects.equal(this.state, that.state)
53                     && com.google.common.base.Objects.equal(this.zip, that.zip);
54         }
55 
56         @Override
57         public int hashCode() {
58             return com.google.common.base.Objects.hashCode(getAddress1(), getCity(), getCity(), getState(), getZip());
59         }
60 
61         @Override
62         public String toString() {
63             return com.google.common.base.Objects.toStringHelper(this).addValue(getAddress1()).addValue(getCity()).addValue(getState()).addValue(getZip()).toString();
64         }
65 
66         public static class Builder {
67 
68             private String address1;
69             private String city;
70             private String state;
71             private String zip;
72 
73             public Builder address1(String address1) {
74                 this.address1 = address1;
75                 return this;
76             }
77 
78             public Address build() {
79                 return new Address(this);
80             }
81 
82             public Builder city(String city) {
83                 this.city = city;
84                 return this;
85             }
86 
87             public Builder state(String state) {
88                 this.state = state;
89                 return this;
90             }
91 
92             public Builder zip(String zip) {
93                 this.zip = zip;
94                 return this;
95             }
96         }
97     }
技术分享

test case:

技术分享
技术分享
  1 package abstractions.domain;
  2 
  3     import static org.hamcrest.Matchers.is;
  4     import static org.junit.Assert.assertThat;
  5 
  6     import java.io.Serializable;
  7 
  8     import org.junit.Before;
  9     import org.junit.Test;
 10     import org.junit.experimental.runners.Enclosed;
 11     import org.junit.runner.RunWith;
 12 
 13     import testhelpers.ComparabilityTestCase;
 14     import testhelpers.EqualsHashCodeTestCase;
 15     import testhelpers.SerializabilityTestCase;
 16 
 17     /**
 18      * The Class AddressTest.
 19      */
 20     @RunWith(Enclosed.class)
 21     public class AddressTest {
 22 
 23         /**
 24          * The Class AddressComparabilityTest.
 25          */
 26         public static class AddressComparabilityTest extends ComparabilityTestCase<Address> {
 27 
 28             @Override
 29             protected Address createEqualInstance() throws Exception {
 30                 return new Address.Builder().address1("2802 South Havana Street").city("Aurora").state("CO").zip("80014").build();
 31             }
 32 
 33             @Override
 34             protected Address createGreaterInstance() throws Exception {
 35                 return new Address.Builder().address1("9839 Carlisle Boulevard NE").city("Albuquerque").state("NM").zip("87110").build();
 36             }
 37 
 38             @Override
 39             protected Address createLessInstance() throws Exception {
 40                 return new Address.Builder().address1("14 Broad St").city("Nashua").state("NH").zip("03064").build();
 41             }
 42         }
 43 
 44         /**
 45          * The Class AddressEqualsHashCodeTest.
 46          */
 47         public static class AddressEqualsHashCodeTest extends EqualsHashCodeTestCase {
 48 
 49             @Override
 50             protected Address createInstance() throws Exception {
 51                 return new Address.Builder().address1("2802 South Havana Street").city("Aurora").state("CO").zip("80014").build();
 52             }
 53 
 54             @Override
 55             protected Address createNotEqualInstance() throws Exception {
 56                 return new Address.Builder().address1("9839 Carlisle Boulevard NE").city("Albuquerque").state("NM").zip("87110").build();
 57             }
 58         }
 59 
 60         /**
 61          * The Class AddressSerializabilityTest.
 62          */
 63         public static class AddressSerializabilityTest extends SerializabilityTestCase {
 64 
 65             @Override
 66             protected Serializable createInstance() throws Exception {
 67                 return new Address.Builder().address1("9839 Carlisle Boulevard NE").city("Albuquerque").state("NM").zip("87110").build();
 68             }
 69         }
 70 
 71         public static class AddressMiscTest {
 72 
 73             private Address address;
 74 
 75             /**
 76              * Setup.
 77              *
 78              * @throws Exception the exception
 79              */
 80             @Before
 81             public void setUp() throws Exception {
 82                 address = new Address.Builder().address1("9839 Carlisle Boulevard NE").city("Albuquerque").state("NM").zip("87110").build();
 83             }
 84 
 85             /**
 86              * Test builder.
 87              */
 88             @Test
 89             public void testBuilder() {
 90                 assertThat(address.getAddress1(), is("9839 Carlisle Boulevard NE"));
 91                 assertThat(address.getCity(), is("Albuquerque"));
 92                 assertThat(address.getState(), is("NM"));
 93                 assertThat(address.getZip(), is("87110"));
 94             }
 95 
 96             @Test
 97             public void testToString() {
 98                 assertThat(address.toString(), is("Address{9839 Carlisle Boulevard NE, Albuquerque, NM, 87110}"));
 99             }
100         }
101     }
技术分享

问题三:不想执行某个类的test case 有什么方法?

回答: 用@Ignore, 如果要让某个类都不执行,@Ignore放在类里,如果不想执行某一个方法,只需要放在方法上。

技术分享
1 @Ignore
2 public class TestClass{
3 
4     @Ignore("Test is ignored as a demonstration")
5     @Test
6     public void testSane() {
7         assertThat(1, is(1));
8     }
9 }
技术分享

问题四:某个test case执行时间太长,有什么办法终止?

回答: Junit4提供了timeout属性。

1 @Test(timeout=1000)
2 public void testWithTimeout() {
3   ...
4 }

 

Junit4还有更重要的@Rule 和 执行顺序。且听下回分解。

 

概要:

 

前一篇文章我们总体介绍了Junit4的用法以及一些简单的测试。之前我有个疑惑,Junit4怎么把一个test case跑起来的,在test case之前和之后我们能做些什么?

 

Junit4执行顺序是怎样的?带着这些问题,我写了这篇文章,仅供参考,不对之处,盼留言指正,感激万分。前一篇文章:【原创】Junit4详解一:Junit总体介绍

 

Junit4 runner总体介绍

 

Junit4编译器在执行TestCase的过 程中利用反射机制,以便我们可以对测试的开始过程中进行一些预处理,如读取元数据信息,拦截异常,数据库操作等,由于Junit4默认的测试执行器 是:BlockJUnit4ClassRunner,我们以这个执行器粗略地做一些研究。在TestCase执行过程中,主要用到以下 类,BlockJUnit4ClassRunner,ParentRunner,Statement,TestRule,Description,RunNotifier,InvokeMethod. 以下简单做些解释。

 

Junit4默认重要类简述,助于理解源代码

 

1. BlockJUnit4ClassRunner:Junit4的默认测试执行器,它有之前版本的runner同样的行为,也就兼容了之前的runner。但是它是基于Statement,实现更加简单,允许用户在执行工作流中某个合适的点插入用户新的操作, 基于这个runner的继承和重用都是可以的,这样能更加具有灵活性。它继承ParentRunner,Junit4要求,执行器的构造函数要把测试类传 进来。这个类的实现了ParentRunner的runChild(真正执行测试的方法,每个测试方法都会执行 runChild),describeChild(FrameworkMethod method)(用来获取测试类的元数据信息,以及方法和类的信息),一些验证的方法,这些验证方法在ParentRunner构造的时候就会开始验证。 另外一个比较重要的方法是:

 

methodBlock(FrameworkMethod method)

 

method里面包含当前要测试的方法。

 

这个方法的作用验证方法能否执行,然后把当前测试类的信息(当前类,测试的方法)传给InvokeMethod,以待后续测试方法的执行,接着获取当前类的元数据信息,保存起来。

 

2. ParentRunner:Junit4测试执行器的基类,它提供了一个测试器所需要的大部分功能。继承它的类需要实现:

 

protected abstract List<T> getChildren();

 

protected abstract Description describeChild(T child);

 

protected abstract void runChild(T child, RunNotifier notifier);

 

3. Statement:在运行期时,执行test case前可以插入一些用户动作,它就是描述这些动作的一个类。继承这个类要实现:

 

技术分享
    /**

     * Run the action, throwing a {@code Throwable} if anything goes wrong.

     */

     public abstract void evaluate() throws Throwable;
技术分享

 

 这个方法,这个方法会先后在ParentRunner.run()和ParentRunner.runLeaf()这两个方法里面调用。另外,我们可以自定义一个Statement,并且实现evaluate()方法。

 

4. TestRule:TestRule 可以描述一个或多个测试方法如何运行和报告信息的接口。在TestRule中可以额外加入一些check,我们可以让一个test case失败/成功,也可以加入一些setup和cleanup要做的事,也可以加入一些log之类的报告信息。总之,跑test case之前的任何事,都可以在里面做。需要实现apply()方法。

 

技术分享
    /**

     * Modifies the method-running {@link Statement} to implement this

     * test-running rule.

     * @param base The {@link Statement} to be modified

     * @param description A {@link Description} of the test implemented in {@code base}

     * @return a new statement, which may be the same as {@code base},

     * a wrapper around {@code base}, or a completely new Statement.

     */

     Statement apply(Statement base, Description description);
技术分享

 

 这两个类的用法可以见后面的综合例子。

 

5. Description:存储着当前单个或多个test case的描述信息。这些信息跟逻辑不关,比如元数据信息等。实例化Description用Description.createTestDescription()方法。

 

 

 

6. RunNotifier:运行时通知器。执行Runner.run(RunNotifier runNotifier)方法时,需要传一个RunNotifier进去,这个RunNotifier是事件的管理器,它能帮助我们监控测试执行的情况。

 

 

 

7. InvokeMethod:最终执行test case里面的测试方法通过这个类来做,这个类会间接调用Method.invoke()方法通知编译器执行@test方法。

 

Junit4启动test case到结束整个过程概述

 

  1. Junit4Builder编译器会构造Test运行器,如BlockJUnit4ClassRunner,BlockJUnit4ClassRunner 会通过自己的构造器,把当前测试类传到runner里。
  2. 运行ParentRunner.run()方 法,run 方法会获取测试类的Description信息,Description信息会包含测试类的信息,然后执行 classBlock(RunNotifier),这个方法获取Statement信息,首先构造一个childrenInvoker,然后在 Statement的evaluate()方法调用runChildren()方法,用来真正地执行test方法,这个步骤会等到测试真正执行后开始做。 现在是先获取Statement会处理三种注解,@Before,@After,@Rule,把标注这些注解的方法分别放在集合里,以便后面能够处理这些 方法。
  3. 准备工作都做好之后,会执行步骤2里从 classBlock(RunNotifier)获取到的Statement的evaluate()方法,这个方法用来对Statement来说是开了一 个口,用户可以自定义Statement的方法,不过在这里,evaluate()主要是来执行步骤2调用的runChildren()方法。
  4. runChildren()方法的作用是:遍 历测试类的所有测试方法(getFilteredChildren),开启线程调度fScheduler,调度线程给每一个测试方法,然后执行 Runnable.run()方法,让测试执行器,让测试执行器可以执行测试类的测试方法(runChild)。
  5. 执行测试方法首先会判断方法是否含有@Ignore注解,如果有,那么忽略它的测试。如果没有那么执行runLeaf()方法。这个方法是真正我们执行测试的开始。
  6. RunLeaf(Statement, Description, RunNotifier),首先Statement是有methodBlock(FrameworkMethod)产生,FrameworkMethod 存着当前要执行的测试方法,在这个方法里,用了反射机制。这时候Junit4会构造RunRules会把Statement, Description apply()到MethodRules, TestRule进去,也就是说,我们在外部构造的带有@Rule,@Before, @After等就在这里执行,如:
    @Rule
    public final TestRule testRule = new CommonRule();

     此时,我们就可以在我们新构建的CommonRule类里面,的apply()方法,做一些对test的预处理,比如预处理连接数据库字符串,读取方法上元数据的信息等;

  7. 然后就真正执行 RunLeaf(Statement, Description, RunNotifier),通过传进来的参数构建EachTestNotifier,执行fireTestStarted,然后,再打开对 话,statement.evaluate(),这个执行过程中,会到InvokeMethod类,然后调用 InvokeMethod.evaluate(),最后调用Method.invoke()方法真正地执行了test实体。测试开始了。

 

备注:就如刚所说的,真正开始测试前,我们可以用apply()进行一些处理,同样地,我们可以在apply()方法中,创建用户Statement,这样就能在evaluate()方法中,做一些操作。如执行脚本,日志等。

 

元数据的执行顺序

 

1. 获取元数据信息的顺序

 

@BeforeClass -> @AfterClass -> ClassRule -> @Test(拿元数据里的expect Exception) -> @Test(拿元数据里的timeout信息) -> @Before -> @After -> @Rule,

 

2. 注解所标注的方法执行顺序

 

@ClassRule(TestRule.apply()) -> @BeforeClass -> @Rule(TestRule.apply())  -> @Before -> @Test(test method1) ->@After -> if existed @Rule, then Statement.evaluate() -> @Rule(TestRule.apply()) -> @Before -> @Test(test method2) -> @After -> if existed @Rule, then Statement.evaluate() … -> @AfterClass -> if existed @ClassRule, then Statement.evaluate()

 

通过Statement.evaluate()执行他们的方法实体,最终执行测试方法的主体。

 

附录:

 

TestRule Statement以及注解标识的方法执行顺序代码示例

 

 

 

技术分享
技术分享
  1 package com.citi.risk.services.credit.facility.impl;
  2 
  3 import java.io.Closeable;
  4 import java.io.IOException;
  5 
  6 import org.junit.After;
  7 import org.junit.AfterClass;
  8 import org.junit.Before;
  9 import org.junit.BeforeClass;
 10 import org.junit.ClassRule;
 11 import org.junit.Rule;
 12 import org.junit.Test;
 13 import org.junit.rules.ExpectedException;
 14 import org.junit.rules.TestRule;
 15 import org.junit.runner.Description;
 16 import org.junit.runners.model.Statement;
 17 
 18 /**
 19  * 执行顺序如下: 默认test方法的执行顺序是随机的,没有顺序
 20  * @ClassRule(TestRule.apply()) -> @BeforeClass -> @Rule(TestRule.apply())  -> @Before 
 21  * -> @Test(test method1) ->@After -> if existed @Rule, then Statement.evaluate() 
 22  * -> @Rule(TestRule.apply()) -> @Before -> @Test(test method2) -> @After 
 23  * -> if existed @Rule, then Statement.evaluate() … -> @AfterClass 
 24  * -> if existed @ClassRule, then Statement.evaluate()
 25  * @author 草原战狼
 26  *
 27  */
 28 public class TestClass {
 29 
 30     @Rule
 31     public ExpectedException expectedException = ExpectedException.none();
 32     
 33     @Rule
 34     public TestRule testRule = new TestRuleValueImpl();
 35     
 36     @Rule
 37     public TestRule testRuleMethod() {
 38         System.out.println();
 39         System.out.println("@Rule Method");
 40         return new TestRuleMethodImpl();
 41     }
 42     @ClassRule
 43     public static TestRule testClassRuleMethod() {
 44         System.out.println("@ClassRule Method");
 45         return new TestRuleMethodImpl();
 46     }
 47 
 48     static class TestRuleValueImpl implements TestRule{
 49         @Override
 50         public Statement apply(Statement base, Description description) {
 51             System.out.println("@Rule property--TestRuleValueImpl execute apply()");
 52             return new StatementValueImpl(base);
 53         }
 54     }
 55 
 56     static class StatementValueImpl extends Statement {
 57         Statement base;
 58         StatementValueImpl(Statement base) {
 59             this.base = base;
 60         }
 61         @Override
 62         public void evaluate() throws Throwable {
 63             System.out.println("@Rule property--StatementValueImpl execute evaluate()");
 64             base.evaluate();
 65         }
 66         
 67     }
 68     static class TestRuleMethodImpl implements TestRule{
 69         @Override
 70         public Statement apply(Statement base, Description description) {
 71             System.out.println("@Rule method--TestRuleMethodImpl execute apply()");
 72             return new StatementMethodImpl(base);
 73         }
 74         
 75     }
 76     
 77     static class StatementMethodImpl extends Statement {
 78         Statement base;
 79         StatementMethodImpl(Statement base) {
 80             this.base = base;
 81         }
 82         @Override
 83         public void evaluate() throws Throwable {
 84             System.out.println("@Rule Method--StatementMethodImpl execute evaluate()");
 85             base.evaluate();
 86         }
 87         
 88     }
 89     static class ExpensiveManagedResource implements Closeable {
 90         @Override
 91         public void close() throws IOException {
 92         }
 93     }
 94 
 95     static class ManagedResource implements Closeable {
 96         @Override
 97         public void close() throws IOException {
 98         }
 99     }
100 
101     @BeforeClass
102     public static void setUpClass() {
103         System.out.println("@BeforeClass setUpClass");
104         myExpensiveManagedResource = new ExpensiveManagedResource();
105     }
106 
107     @AfterClass
108     public static void tearDownClass() throws IOException {
109         System.out.println("@AfterClass tearDownClass");
110         myExpensiveManagedResource.close();
111         myExpensiveManagedResource = null;
112     }
113 
114     private ManagedResource myManagedResource;
115     private static ExpensiveManagedResource myExpensiveManagedResource;
116 
117     private void println(String string) {
118         System.out.println(string);
119     }
120 
121     @Before
122     public void setUp() {
123         this.println("@Before setUp");
124         this.myManagedResource = new ManagedResource();
125     }
126 
127     @After
128     public void tearDown() throws IOException {
129         this.println("@After tearDown");
130         this.myManagedResource.close();
131         this.myManagedResource = null;
132         this.println("   ");
133     }
134 
135     @Test
136     public void test1() {
137         this.println("   @Test test1() begin");
138         this.println("   @Test test1() execute during evaluate()");
139         this.println("   @Test test1() finished");
140     }
141 
142     @Test
143     public void test2() {
144         this.println("   @Test test2() begin");
145         this.println("   @Test test2() execute during evaluate()");
146         this.println("   @Test test2() finished");
147     }
148 
149     @Test
150     public void test3() {
151         this.println("   @Test test3() begin");
152         String hi = "   @Test test3() execute during evaluate()";
153         expectedException.expect(Exception.class);
154         expectedException.expectMessage("ddd");
155         this.println(hi);
156         this.println("   @Test test3() finished.");
157     }
158 }
技术分享

 

  执行的结果如下:

 

 

 

技术分享
 1 @ClassRule Method
 2 @Rule method--TestRuleMethodImpl execute apply()
 3 @Rule Method--StatementMethodImpl execute evaluate()
 4 @BeforeClass setUpClass  // 预备期结束
 5  //  第一个测试方法开始到结束
 6 @Rule Method
 7 @Rule method--TestRuleMethodImpl execute apply()
 8 @Rule property--TestRuleValueImpl execute apply()
 9 @Rule property--StatementValueImpl execute evaluate()
10 @Rule Method--StatementMethodImpl execute evaluate()
11 @Before setUp
12    @Test test1() begin
13    @Test test1() execute during evaluate()
14    @Test test1() finished
15 @After tearDown
16    
17 // 第二个方法开始到结束,我们可以在apply() 和 evaluate()这两个方法做一些操作。
18 @Rule Method
19 @Rule method--TestRuleMethodImpl execute apply()
20 @Rule property--TestRuleValueImpl execute apply()
21 @Rule property--StatementValueImpl execute evaluate()
22 @Rule Method--StatementMethodImpl execute evaluate()
23 @Before setUp
24    @Test test2() begin
25    @Test test2() execute during evaluate()
26    @Test test2() finished
27 @After tearDown
28    
29 // 第三个方法,这三个方法执行的顺序是随机的,当然Junit4提供了某些排序方式可以处理
30 @Rule Method
31 @Rule method--TestRuleMethodImpl execute apply()
32 @Rule property--TestRuleValueImpl execute apply()
33 @Rule property--StatementValueImpl execute evaluate()
34 @Rule Method--StatementMethodImpl execute evaluate()
35 @Before setUp
36    @Test test3() begin
37    @Test test3() execute during evaluate()
38    @Test test3() finished.
39 @After tearDown
40    
41 @AfterClass tearDownClass
技术分享

 

Junit 4

原文:http://www.cnblogs.com/zhouzf007/p/4915855.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!