※@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,但也不會被執行