※@Rule
※內鍵的 Rule
※所謂內鍵,就是在 org.junit.rules 這包裡import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.Timeout; public class AppTest3 { @Rule public Timeout timeout1 = Timeout.millis(10); // public Timeout timeout2 = new Timeout(10, TimeUnit.MILLISECONDS); @Rule public final ExpectedException thrown = ExpectedException.none(); @Test public void xxx() throws InterruptedException { Thread.sleep(5); } @Test public void ooo() throws InterruptedException { Thread.sleep(5); } @Test public void zzz() throws InterruptedException { thrown.expect(ArithmeticException.class); int i = 1 / 0; } }
※這個annotation是 4.7 版增加的,宣告時一定要 public
※@Test 裡的 timeout 和 expected 都有,但宣告 @Rule 是全域的,每個方法都會遵從
※ExpectedException.none() 表示不能有例外
※Verifier
原本的測試結束後,會執行這裡的邏輯,這裡的邏輯過了,測試才會過@Rule public Verifier verifier = new Verifier() { @Override protected void verify() { Assert.assertEquals(1, 1); } };
※可看高手寫的文章
※自訂 Rule
import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; public class RuleTest implements TestRule { public Statement apply(Statement base, Description des) { return new Statement() { @Override public void evaluate() throws Throwable { System.out.println("className=" + des.getClassName()); System.out.println("displayName=" + des.getDisplayName()); System.out.println("methodName=" + des.getMethodName()); System.out.println("children=" + des.getChildren()); System.out.println("annotations=" + des.getAnnotations()); base.evaluate(); } }; } }
※實作 TestRule 後,覆寫 apply 方法
※測試
@Rule public RuleTest ruleTest = new RuleTest(); @Test public void xxx() throws InterruptedException { Thread.sleep(5); System.out.println("aaa\r\n"); } @Test public void ooo() throws InterruptedException { Thread.sleep(5); System.out.println("bbb\r\n"); }
※如果不想寫 class 去實作,還可以用匿名和 lambda,如下:
@Rule public TestRule xxx = new TestRule() { @Override public Statement apply(Statement base, Description des) { System.out.println("className=" + des.getClassName()); System.out.println("displayName=" + des.getDisplayName()); System.out.println("methodName=" + des.getMethodName()); System.out.println("children=" + des.getChildren()); System.out.println("annotations=" + des.getAnnotations()); // try { // base.evaluate(); // } catch (Throwable e) { // e.printStackTrace(); // } return base; } }; @Rule public TestRule ooo = (base, des) -> { System.out.println("className=" + des.getClassName()); System.out.println("displayName=" + des.getDisplayName()); System.out.println("methodName=" + des.getMethodName()); System.out.println("children=" + des.getChildren()); System.out.println("annotations=" + des.getAnnotations()); return base; };
※此時不用寫 base.evaluate(),否則會執行兩次 @Test 裡的方法
※常用方法
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; import org.hamcrest.CoreMatchers; import org.junit.Test; public class AppTest { @Test public void testApp() { assertEquals(5, 5); assertEquals("我錯了", 5, 5); AppTest t = new AppTest(); assertSame(t, t); // Assert.fail();//一定不會過 final Integer FIVE = 5; assertThat(FIVE, CoreMatchers.anything());// 一定會過 assertThat(FIVE, CoreMatchers.is(5));// 5等於5嗎? assertThat(FIVE, CoreMatchers.not(10));// 5是10嗎 assertThat(FIVE, CoreMatchers.notNullValue());// 5不是null嗎 // 全部是5才會過 assertThat(FIVE, CoreMatchers.allOf(CoreMatchers.is(5), CoreMatchers.is(5), CoreMatchers.is(5))); // 有一個是5就會過 assertThat(FIVE, CoreMatchers.anyOf(CoreMatchers.is(1), CoreMatchers.is(5), CoreMatchers.is(2))); } }
※很多 assertXxx 有很多的 overloading 方法,有些第一個參數都是String,可以打一些字,出錯時會顯示裡面的內容
※測試其他類別
@RunWith(Suite.class) @Suite.SuiteClasses({ TestXxx.class ,TestOoo.class }) public class TestHaHaHa { }
※可以測試 TestXxx 和 TestOoo 這兩個類別
※經過測試,TestHaHaHa 裡面只能有一個 @Test,但也不會被執行
沒有留言:
張貼留言