¶ÔÓÚËùÓÐµÄ Java ¿ª·¢ÈËÔ±À´Ëµ£¬Äã¿ÉÒÔûÓÐÌý˵¹ý Spring »òÊÇ
Hibernate ¿ò¼Ü£¬µ«ÊÇÒ»¶¨Ìý˵¹ý JUnit¡£JUnit ×÷Ϊ Java µ¥Ôª²âÊԵıÇ׿ÓëÊÂʵÉϵıê×¼£¬Ôڷdz£¶àµÄÏîÄ¿Öб»Ê¹Ó᣼´±ãÐÂÐ˵ĵ¥Ôª²âÊÔ¿ò¼Ü£¬Èç
TestNG µÈ£¬²»¶Ï³öÏÖ£¬JUnit µÄÖØÒªÐÔÈÔÈ»ÊDz»ÑÔ¶øÓ÷µÄ¡£Ä¿Ç°¹ã·ºÊ¹ÓõÄÊÇ JUnit 4 °æ±¾£¬¶ø
JUnit ¼´½«ÓÀ´ËüµÄ×îа汾 JUnit 5¡£JUnit 5 ÔÚÔö¼ÓÁ˺ܶàµÄÐÂÌØÐÔµÄͬʱ£¬ÓÖ±£³ÖÁ˶Ô
JUnit 4 µÄÏòºó¼æÈÝÐÔ¡£±¾ÎÄ¶Ô JUnit 5 ½øÐÐÁËÏêϸµÄ½éÉÜ¡£
JUnit 5 ¼ò½é
Óë֮ǰµÄ°æ±¾²»Í¬£¬JUnit 5 ÓÉÈý¸ö²»Í¬µÄÄ£¿é×é³É¡£µÚÒ»¸öÄ£¿éÊÇ JUnit ƽ̨£¬ÆäÖ÷Òª×÷ÓÃÊÇÔÚ
JVM ÉÏÆô¶¯²âÊÔ¿ò¼Ü¡£Ëü¶¨ÒåÁËÒ»¸ö³éÏóµÄ TestEngine API À´¶¨ÒåÔËÐÐÔÚÆ½Ì¨ÉϵIJâÊÔ¿ò¼Ü£¬Í¬Ê±»¹Ö§³Öͨ¹ýÃüÁîÐС¢Gradle
ºÍ Maven À´ÔËÐÐÆ½Ì¨¡£µÚ¶þ¸öÄ£¿éÊÇ JUnit Jupiter£¬°üº¬ÁË JUnit 5 ×îеıà³ÌÄ£ÐͺÍÀ©Õ¹»úÖÆ¡£µÚÈý¸öÄ£¿éÊÇ
JUnit Vintage£¬ÔÊÐíÔÚÆ½Ì¨ÉÏÔËÐÐ JUnit 3 ºÍ JUnit 4 µÄ²âÊÔÓÃÀý¡£
JUnit 5 ¶Ô Java ÔËÐл·¾³µÄ×îµÍÒªÇóÊÇ Java 8¡£¿ÉÒÔÔÚ Eclipse ºÍ IntelliJ
IDEA ÉÏÔËÐÐ JUnit 5 ²âÊÔ¡£±¾ÎĵÄʾÀý»ùÓÚ IntelliJ IDEA ÉÏ¿ª·¢£¬²¢Ê¹Óà Gradle
×÷Ϊ¹¹½¨¹¤¾ß¡£²»¹ýĿǰ IDE ¶Ô JUnit 5 µÄÖ§³Ö»¹±È½ÏÓÐÏÞ£¬Ö»ÓÐ×îа汾µÄ IntelliJ
IDEA ÔÉúÖ§³Ö£¬ÔÚÆäËü IDE ÉÏÐèҪʹÓÃÃüÁîÐй¤¾ßÀ´ÔËÐС£
±àд²âÊÔÓÃÀý
JUnit 5 ¶Ô±àдµ¥Ôª²âÊÔÓÃÀýµÄ·½Ê½×öÁËһϵÁеĸĽø£¬ÈçϽéÉÜ¡£
JUnit 5 ×¢½â
JUnit 5 ÌṩÁËһЩ³£ÓõÄ×¢½âÔÚ±àд²âÊÔÓÃÀýµÄʱºòʹÓá£ÆäÖеÄһЩע½âºÍ JUnit 4 µÄ×¢½âÓÐÏàͬµÄÃû³Æ£¬²»¹ýËùÔÚµÄ
Java °ü±ä³ÉÁË org.junit.jupiter.api¡£³£ÓõÄ×¢½â¼û±í 1¡£
±í 1. JUnit 5 ³£ÓÃ×¢½â

Çåµ¥ 1 Öиø³öÁËʹÓÃÕâЩע½â±àдµÄµ¥Ôª²âÊÔÓÃÀý¡£
Çåµ¥ 1. ʹÓó£ÓÃ×¢½âµÄµ¥Ôª²âÊÔÓÃÀý
@DisplayName("Calculator") public class CalculatorTest { private Calculator calculator; @BeforeAll public static void init() { System.out.println("Start testing"); } @BeforeEach public void create() { this.calculator = new Calculator(); } @AfterEach public void destroy() { this.calculator = null; } @AfterAll public static void cleanup() { System.out.println("Finish testing"); } @Test @DisplayName("Test 1 + 2 = 3") public void testAdd() { assertEquals(3, this.calculator.add(1, 2)); } @Test @DisplayName("Test 3 - 2 = 1") public void testSubtract() { assertEquals(1, this.calculator.subtract(3, 2)); } @Disabled @Test @DisplayName("disabled test") public void ignoredTest() { System.out.println("This test is disabled"); } } |
ÔÚÕâЩע½âÖУ¬×îʵÓõÄÓ¦¸ÃÊÇ@DisplayName¡£Í¨¹ý@DisplayName£¬¿ª·¢ÈËÔ±¿ÉÒÔΪÿ¸ö²âÊÔÓÃÀýÌí¼Ó¸ü¾ßÌåµÄÃû×Ö£¬¸üÈÝÒ×´«´ïÓÃÀýËùÒª²âÊÔµÄÄÚÈÝ¡£
ͨ¹ý@Tag ×¢½â¿ÉÒÔΪ²âÊÔÀà»ò·½·¨Ìí¼Ó±êÇ©£¬µ«ÊDz»Í¬µÄ±êǩֻÊÇͨ¹ý×Ö·û´®À´½øÐÐÇø·Ö£¬²¢²»ÊÇÀàÐͰ²È«µÄ¡£Ò»¸öƴд´íÎó¾Í¿ÉÄÜÔì³É±êǩûÓб»ÕýÈ·Ó¦Ó᣸üºÃµÄ×ö·¨ÊÇʹÓÃÀàÐͰ²È«µÄԪע½â£¨meta
annotation£©¡£±àÒëÆ÷»á¶ÔԪע½â±êÇ©µÄÕýÈ·ÐÔ½øÐÐÑéÖ¤£¬´Ó¶ø¼õÉÙÎÞÒâµÄ´íÎó¡£Çåµ¥ 2 Öж¨ÒåÁËԪע½â±êÇ©@Remote£¬¶ÔÓ¦ÓÚ±êÇ©
remote¡£
Çåµ¥ 2. Ԫע½â±êÇ©
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Tag("remote") public @interface Remote { } |
Çåµ¥ 3 ÖÐչʾÁË@Remote µÄÓ÷¨¡£Ê¹ÓÃ@Remote µÄ×÷ÓõÈͬÓÚ@Tag("Remote")£¬Îª
testGetUser ·½·¨Ìí¼ÓÁ˱êÇ© remote¡£Ê¹ÓÃ@Remote ²»½öÌá¸ßÁË´úÂëµÄ¿É¶ÁÐÔ£¬Ò²¿ÉÒÔ±ÜÃâÎÞÒâµÄƴд´íÎó´øÀ´µÄÎÊÌâ¡£
Çåµ¥ 3. ʹÓÃԪע½â±êÇ©
@DisplayName("Remote test") public class RemoteTest { @Test @Remote public void testGetUser() { System.out.println("Get user"); } } |
JUnit 5 ¶ÏÑÔ
¶ÏÑÔ£¨assertions£©ÊDzâÊÔ·½·¨ÖеĺËÐIJ¿·Ö£¬ÓÃÀ´¶Ô²âÊÔÐèÒªÂú×ãµÄÌõ¼þ½øÐÐÑéÖ¤¡£ÕâЩ¶ÏÑÔ·½·¨¶¼ÊÇ
org.junit.jupiter.api.Assertions µÄ¾²Ì¬·½·¨¡£JUnit 5 ÄÚÖõĶÏÑÔ¿ÉÒÔ·Ö³ÉÈçϼ¸¸öÀà±ð£º
µÚÒ»ÀàÊǼòµ¥¶ÏÑÔ£¬ÓÃÀ´¶Ôµ¥¸öÖµ½øÐмòµ¥µÄÑéÖ¤£¬³£Óõķ½·¨¼û±í 2¡£
±í 2. ³£ÓõĶÏÑÔ·½·¨

ÕâЩ·½·¨¶¼Óжà¸öÖØÔØ·½·¨£¬¿ÉÒÔÌṩ¶îÍâµÄÏûÏ¢À´×÷Ϊ¶ÏÑÔ²»Âú×ãʱµÄÌáʾÏûÏ¢£¬»¹¿ÉÒÔ½ÓÊÜ Java 8 ÖеÄ
Supplier ½Ó¿ÚÀ´»ñȡҪÅжϵÄÖµºÍÏÔʾµÄÏûÏ¢¡£Çåµ¥ 4 Öиø³öÁ˼òµ¥¶ÏÑÔµÄʹÓÃʾÀý¡£
Çåµ¥ 4. ¼òµ¥¶ÏÑÔ
@Test @DisplayName("simple assertion") public void simple() { assertEquals(3, 1 + 2, "simple math"); assertNotEquals(3, 1 + 1); assertNotSame(new Object(), new Object()); Object obj = new Object(); assertSame(obj, obj); assertFalse(1 > 2); assertTrue(1 < 2); assertNull(null); assertNotNull(new Object()); } |
µÚ¶þÀàÊÇͨ¹ý assertArrayEquals ·½·¨À´ÅжÏÁ½¸ö¶ÔÏó»òÔʼÀàÐ͵ÄÊý×éÊÇ·ñÏàµÈ£¬ÈçÇåµ¥ 5
Ëùʾ¡£
Çåµ¥ 5. assertArrayEquals ·½·¨µÄʾÀý
@Test @DisplayName("array assertion") public void array() { assertArrayEquals(new int[]{1, 2}, new int[] {1, 2}); } |
µÚÈýÀàÊÇͨ¹ý assertAll ·½·¨À´ÅжÏÒ»×é¶ÏÑÔÊÇ·ñÂú×ã¡£assertAll ·½·¨½ÓÊܶà¸ö org.junit.jupiter.api.Executable
º¯Êýʽ½Ó¿ÚµÄʵÀý×÷ΪҪÑéÖ¤µÄ¶ÏÑÔ£¬¿ÉÒÔͨ¹ý lambda ±í´ïʽºÜÈÝÒ×µÄÌṩÕâЩ¶ÏÑÔ£¬ÈçÇåµ¥ 6 Ëùʾ¡£
Çåµ¥ 6. assertAll ·½·¨µÄʾÀý
@Test @DisplayName("assert all") public void all() { assertAll("Math", () -> assertEquals(2, 1 + 1), () -> assertTrue(1 > 0) ); } |
µÚËÄÀàÊÇͨ¹ý assertThrows »ò expectThrows À´ÅжÏÊÇ·ñÅ׳öÆÚÍûµÄÒì³£ÀàÐÍ¡£Á½¸ö·½·¨µÄ²ÎÊý¶¼ÊÇËùÆÚÍûµÄÒì³£ÀàÐͺͶÔÓ¦µÄ
Executable ½Ó¿ÚµÄʵÏÖ¶ÔÏó£¬Çø±ðÔÚÓÚ expectThrows ·½·¨»á·µ»ØÅ׳öµÄÒì³£¶ÔÏó¡£ÔÚÇåµ¥
7 ÖУ¬1/0 »áÅ׳ö ArithmeticException Òì³££¬assertThrows ÓÃÀ´ÑéÖ¤ÕâÒ»µã¡£
Çåµ¥ 7. assertThrows ºÍ expectThrows ·½·¨µÄʾÀý
@Test @DisplayName("throws exception") public void exception() { assertThrows(ArithmeticException.class, () -> System.out.println(1 / 0)); } |
µÚÎåÀàÊÇ fail ·½·¨£¬ÓÃÀ´Ê¹Ò»¸ö²âÊÔ·½·¨Ê§°Ü¡£Çåµ¥ 8 ÖеIJâÊÔ»áÖ±½Óʧ°Ü¡£
Çåµ¥ 8. ͨ¹ý fail ·½·¨Ö±½ÓʹµÃ²âÊÔʧ°Ü
@Test @DisplayName("fail") public void shouldFail() { fail("This should fail"); } |
JUnit 5 ǰÖÃÌõ¼þ
JUnit 5 ÖеÄǰÖÃÌõ¼þ£¨assumptions£©ÀàËÆÓÚ¶ÏÑÔ£¬²»Í¬Ö®´¦ÔÚÓÚ²»Âú×ãµÄ¶ÏÑÔ»áʹµÃ²âÊÔ·½·¨Ê§°Ü£¬¶ø²»Âú×ãµÄǰÖÃÌõ¼þÖ»»áʹµÃ²âÊÔ·½·¨µÄÖ´ÐÐÖÕÖ¹¡£Ç°ÖÃÌõ¼þ¿ÉÒÔ¿´³ÉÊDzâÊÔ·½·¨Ö´ÐеÄǰÌᣬµ±¸ÃǰÌá²»Âú×ãʱ£¬¾ÍûÓмÌÐøÖ´ÐеıØÒª¡£ÔÚÇåµ¥
9 ÖУ¬assumeTrue ºÍ assumFalse È·±£¸ø¶¨µÄÌõ¼þΪ true »ò false£¬²»Âú×ãÌõ¼þ»áʹµÃ²âÊÔÖ´ÐÐÖÕÖ¹¡£assumingThat
µÄ²ÎÊýÊDZíʾÌõ¼þµÄ²¼¶ûÖµºÍ¶ÔÓ¦µÄ Executable ½Ó¿ÚµÄʵÏÖ¶ÔÏó¡£Ö»ÓÐÌõ¼þÂú×ãʱ£¬Executable
¶ÔÏó²Å»á±»Ö´ÐУ»µ±Ìõ¼þ²»Âú×ãʱ£¬²âÊÔÖ´Ðв¢²»»áÖÕÖ¹¡£
Çåµ¥ 9. JUnit 5 ǰÖÃÌõ¼þ
@DisplayName("Assumptions") public class AssumptionsTest { private final String environment = "DEV"; @Test @DisplayName("simple") public void simpleAssume() { assumeTrue(Objects.equals(this.environment, "DEV")); assumeFalse(() -> Objects.equals(this.environment, "PROD")); } @Test @DisplayName("assume then do") public void assumeThenDo() { assumingThat( Objects.equals(this.environment, "DEV"), () -> System.out.println("In DEV") ); } } |
ǶÌײâÊÔ
JUnit 5 ¿ÉÒÔͨ¹ý Java ÖеÄÄÚ²¿ÀàºÍ@Nested ×¢½âʵÏÖǶÌײâÊÔ£¬´Ó¶ø¿ÉÒÔ¸üºÃµÄ°ÑÏà¹ØµÄ²âÊÔ·½·¨×éÖ¯ÔÚÒ»Æð¡£ÔÚÄÚ²¿ÀàÖпÉÒÔʹÓÃ@BeforeEach
ºÍ@AfterEach ×¢½â£¬¶øÇÒǶÌ׵IJã´ÎûÓÐÏÞÖÆ¡£Çåµ¥ 10 Öиø³öÁËʹÓÃǶÌײâÊÔµÄʾÀý£¬ÓÃÀ´²âÊÔ
HashMap µÄ¹¦ÄÜ¡£
Çåµ¥ 10. ǶÌײâÊÔ
@DisplayName("Nested tests for HashMap") public class MapNestedTest { Map<String, Object> map; @Nested @DisplayName("when a new") class WhenNew { @BeforeEach void create() { map = new HashMap<>(); } @Test @DisplayName("is empty") void isEmpty() { assertTrue(map.isEmpty()); } @Nested @DisplayName("after adding a new entry") class AfterAdd { String key = "key"; Object value = "value"; @BeforeEach void add() { map.put(key, value); } @Test @DisplayName("is not empty") void isNotEmpty() { assertFalse(map.isEmpty()); } @Test @DisplayName("returns value when getting by key") void returnValueWhenGettingByKey() { assertEquals(value, map.get(key)); } @Nested @DisplayName("after removing the entry") class AfterRemove { @BeforeEach void remove() { map.remove(key); } @Test @DisplayName("is empty now") void isEmpty() { assertTrue(map.isEmpty()); } @Test @DisplayName("returns null when getting by key") void returnNullForKey() { assertNull(map.get(key)); } } } } } |
ÒÀÀµ×¢Èë
ÔÚ JUnit 5 ֮ǰ£¬±ê×¼µÄ²âÊÔÀàºÍ²âÊÔ·½·¨ÊDz»ÔÊÐíÓжîÍâµÄ²ÎÊýµÄ¡£Õâ¸öÏÞÖÆÔÚ JUnit 5 ±»È¡ÏûÁË¡£JUnit
5 ³ýÁËÌṩÄÚÖõıê×¼²ÎÊýÖ®Í⣬»¹¿ÉÒÔͨ¹ýÀ©Õ¹»úÖÆÀ´Ö§³Ö¶îÍâµÄ²ÎÊý¡£
µ±²ÎÊýµÄÀàÐÍÊÇ org.junit.jupiter.api.TestInfo ʱ£¬JUnit 5 »áÔÚÔËÐвâÊÔʱÌṩһ¸ö
TestInfo ½Ó¿ÚµÄ¶ÔÏó¡£Í¨¹ý TestInfo ½Ó¿Ú£¬¿ÉÒÔ»ñÈ¡µ½µ±Ç°²âÊÔµÄÏà¹ØÐÅÏ¢£¬°üÀ¨ÏÔʾÃû³Æ¡¢±êÇ©¡¢²âÊÔÀàºÍ²âÊÔ·½·¨£¬ÈçÇåµ¥
11 Ëùʾ¡£
Çåµ¥ 11. TestInfo ÒÀÀµ×¢Èë
@Test @DisplayName("test info") public void testInfo(final TestInfo testInfo) { System.out.println(testInfo.getDisplayName()); } |
µ±²ÎÊýµÄÀàÐÍÊÇ org.junit.jupiter.api.TestReporter ʱ£¬ÔÚÔËÐвâÊÔʱ£¬Í¨¹ý×÷Ϊ²ÎÊý´«ÈëµÄ
TestReporter ½Ó¿Ú¶ÔÏó£¬À´Êä³ö¶îÍâµÄ¼üÖµ¶ÔÐÅÏ¢¡£ÕâЩÐÅÏ¢¿ÉÒÔ±»²âÊÔÖ´ÐеļàÌýÆ÷ TestExecutionListener
´¦Àí£¬Ò²¿ÉÒÔ±»Êä³öµ½²âÊÔ½á¹û±¨¸æÖУ¬ÈçÇåµ¥ 12 Ëùʾ¡£
Çåµ¥ 12. TestReporter ÒÀÀµ×¢Èë
@Test @DisplayName("test reporter") public void testReporter(final TestReporter testReporter) { testReporter.publishEntry("name", "Alex"); } |
³ýÁË TestInfo ºÍ TestReporter Ö®Í⣬Ҳ¿ÉÒÔͨ¹ý JUnit 5 µÄÀ©Õ¹»úÖÆÀ´Ìí¼Ó¶ÔÆäËûÀàÐͲÎÊýµÄÖ§³Ö¡£½«ÔÚÏÂÃæ¹ØÓÚ
JUnit 5 À©Õ¹»úÖÆµÄÒ»½ÚÖнøÐнéÉÜ¡£
¶¯Ì¬²âÊÔ
ĿǰËù½éÉÜµÄ JUnit 5 ²âÊÔ·½·¨µÄ´´½¨¶¼ÊǾ²Ì¬µÄ£¬ÔÚ±àÒëʱ¿Ì¾ÍÒѾ´æÔÚ¡£JUnit 5 ÐÂÔöÁ˶Զ¯Ì¬²âÊÔµÄÖ§³Ö£¬¿ÉÒÔÔÚÔËÐÐʱ¶¯Ì¬´´½¨²âÊÔ²¢Ö´ÐС£Í¨¹ý¶¯Ì¬²âÊÔ£¬¿ÉÒÔÂú×ãһЩ¾²Ì¬²âÊÔÎÞ·¨½âµÄÐèÇó£¬Ò²¿ÉÒÔÍê³ÉÒ»Ð©ÖØ¸´ÐԺܸߵIJâÊÔ¡£±ÈÈ磬ÓÐЩ²âÊÔÓÃÀý¿ÉÄÜÒÀÀµÔËÐÐʱµÄ±äÁ¿£¬ÓÐʱºò»áÐèÒªÉú³ÉÉϰٸö²»Í¬µÄ²âÊÔÓÃÀý¡£ÕâЩ³¡¾°¶¼ÊǶ¯Ì¬²âÊÔ¿ÉÒÔ·¢»ÓÆä³¤´¦µÄµØ·½¡£¶¯Ì¬²âÊÔÊÇͨ¹ýеÄ@TestFactory
×¢½âÀ´ÊµÏֵġ£²âÊÔÀàÖеķ½·¨¿ÉÒÔÌí¼Ó@TestFactory ×¢½âµÄ·½·¨À´ÉùÃ÷ÆäÊÇ´´½¨¶¯Ì¬²âÊԵŤ³§·½·¨¡£ÕâÑùµÄ¹¤³§·½·¨ÐèÒª·µ»Ø
org.junit.jupiter.api.DynamicTest ÀàµÄ¼¯ºÏ£¬¿ÉÒÔÊÇ Stream¡¢Collection¡¢Iterable
»ò Iterator ¶ÔÏó¡£Ã¿¸ö±íʾ¶¯Ì¬²âÊ﵀ DynamicTest ¶ÔÏóÓÉÏÔʾÃû³ÆºÍ¶ÔÓ¦µÄ Executable
½Ó¿ÚµÄʵÏÖ¶ÔÏóÀ´×é³É¡£Çåµ¥ 13 ÖÐչʾÁË@TestFactory µÄʾÀý¡£
Çåµ¥ 13. ¶¯Ì¬²âÊÔ
@TestFactory public Collection<DynamicTest> simpleDynamicTest() { return Collections.singleton(dynamicTest ("simple dynamic test", () -> assertTrue(2 > 1))); } |
DynamicTest ÌṩÁËÒ»¸ö¾²Ì¬·½·¨ stream À´¸ù¾ÝÊäÈëÉú³É¶¯Ì¬²âÊÔ£¬ÈçÇåµ¥ 14 Ëùʾ¡£
Çåµ¥ 14. ͨ¹ý stream ·½·¨À´Éú³É¶¯Ì¬²âÊÔ
@TestFactory public Stream<DynamicTest> streamDynamicTest() { return stream( Stream.of("Hello", "World").iterator(), (word) -> String.format("Test - %s", word), (word) -> assertTrue(word.length() > 4) ); } |
Ö´ÐвâÊÔÓÃÀý
JUnit 5 ÌṩÁËÈýÖÖ²»Í¬µÄ·½Ê½À´Ö´ÐвâÊÔÓÃÀý£¬·Ö±ðÊÇͨ¹ý Gradle ²å¼þ¡¢Maven ²å¼þºÍÃüÁîÐÐÀ´ÔËÐС£
Gradle
JUnit 5 ÌṩÁË Gradle ²å¼þ£¬ÔÚ Gradle ÏîÄ¿ÖÐÔËÐе¥Ôª²âÊÔ£¬ÈçÇåµ¥ 15 Ëùʾ¡£
Çåµ¥ 15. ʹÓà JUnit 5 µÄ Gradle ²å¼þ
buildscript { repositories { mavenCentral() } dependencies { classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-M2' } } apply plugin: 'org.junit.platform.gradle.plugin' |
ÔÚÆôÓÃÁË Gradle ²å¼þÖ®ºó£¬¿ÉÒÔͨ¹ý junitPlatformTest ÈÎÎñÀ´ÔËÐе¥Ôª²âÊÔ¡£¿ÉÒÔÔÚ
Gradle ½Å±¾ÖжԲå¼þ½øÐж¨ÖÆ£¬Èçͨ¹ý reportsDir ÉèÖòâÊÔ½á¹û±¨¸æµÄÉú³É·¾¶£¬Í¨¹ý tags
À´ÉèÖðüº¬»òÅųýµÄ±êÇ©Ãû³Æ£¬ÈçÇåµ¥ 16 Ëùʾ¡£
Çåµ¥ 16. ÅäÖà JUnit 5 µÄ Gradle ²å¼þ
junitPlatform { platformVersion 1.0 reportsDir "build/test-results/junit-platform" tags { include 'fast', 'smoke' } } |
Maven
ÔÚ Maven ÏîÄ¿ÖпÉÒÔͨ¹ý Surefire ²å¼þÀ´ÔËÐÐ JUnit 5 ²âÊÔ£¬Ö»ÐèÒªÔÚ POM ÎļþÖнøÐÐÅäÖü´¿É¡£ÈçÇåµ¥
17 Ëùʾ¡£
Çåµ¥ 17. ÔÚ Maven ÏîÄ¿ÖÐʹÓà JUnit 5
<build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.19</version> <dependencies> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-surefire-provider</artifactId> <version>1.0.0-M2</version> </dependency> </dependencies> </plugin> </plugins> </build> |
ÃüÁîÐÐ
³ýÁË Gradle ºÍ Maven Ö®Í⣬»¹¿ÉÒÔͨ¹ýÃüÁîÐÐÀ´ÔËÐÐ JUnit 5 ²âÊÔ¡£Ö»ÐèÒªÖ±½ÓÔËÐÐ
Java Àà org.junit.platform.console.ConsoleLauncher ¼´¿É¡£ConsoleLauncher
ÌṩÁ˲»Í¬µÄÃüÁîÐвÎÊýÀ´ÅäÖòâÊÔÔËÐеÄÐÐΪ£¬Èç-n À´Ö¸¶¨°üº¬µÄ Java ÀàÃûÂú×ãµÄģʽ£¬-t À´°üº¬±êÇ©£¬-T
À´Åųý±êÇ©¡£
À©Õ¹»úÖÆ
JUnit 5 ÌṩÁ˱ê×¼µÄÀ©Õ¹»úÖÆÀ´ÔÊÐí¿ª·¢ÈËÔ±¶Ô JUnit 5 µÄ¹¦ÄܽøÐÐÔöÇ¿¡£JUnit 5 ÌṩÁ˺ܶàµÄ±ê×¼À©Õ¹½Ó¿Ú£¬µÚÈý·½¿ÉÒÔÖ±½ÓʵÏÖÕâЩ½Ó¿ÚÀ´Ìṩ×Ô¶¨ÒåµÄÐÐΪ¡£Í¨¹ý@ExtendWith
×¢½â¿ÉÒÔÉùÃ÷ÔÚ²âÊÔ·½·¨ºÍÀàµÄÖ´ÐÐÖÐÆôÓÃÏàÓ¦µÄÀ©Õ¹¡£
À©Õ¹µÄÆôÓÃÊǼ̳еģ¬Õâ¼È°üÀ¨²âÊÔÀà±¾ÉíµÄ²ã´Î½á¹¹£¬Ò²°üÀ¨²âÊÔÀàÖеIJâÊÔ·½·¨¡£Ò²¾ÍÊÇ˵£¬²âÊÔÀà»á¼Ì³ÐÆä¸¸ÀàÖеÄÀ©Õ¹£¬²âÊÔ·½·¨»á¼Ì³ÐÆäËùÔÚÀàÖеÄÀ©Õ¹¡£³ý´ËÖ®Í⣬ÔÚÒ»¸ö²âÊÔÉÏÏÂÎÄÖУ¬Ã¿Ò»¸öÀ©Õ¹Ö»ÄܳöÏÖÒ»´Î¡£
´´½¨À©Õ¹
JUnit 5 ÖеÄÀ©Õ¹·Ç³£ÈÝÒ×´´½¨£¬Ö»ÊÇʵÏÖÁËÌØ¶¨½Ó¿ÚµÄ Java Àà¡£JUnit 5 µÄÀ©Õ¹¶¼ÐèҪʵÏÖ
org.junit.jupiter.api.extension.Extension ½Ó¿Ú£¬²»¹ý¸Ã½Ó¿ÚÖ»ÊÇÒ»¸ö±ê¼Ç½Ó¿Ú£¬²¢Ã»ÓÐÈκÎÐèҪʵÏֵľßÌå·½·¨¡£ÕæÕýÆð×÷ÓõÄÊÇ
Extension µÄ×Ó½Ó¿Ú£¬×÷Ϊ JUnit 5 ÌṩµÄÀ©Õ¹µã¡£
²âÊÔÖ´ÐÐÌõ¼þ
ContainerExecutionCondition ºÍ TestExecutionCondition
½Ó¿ÚÓÃÀ´ÅäÖÃÊÇ·ñÆôÓòâÊÔÀà»ò²âÊÔ·½·¨¡£Ç°ÃæÌáµ½µÄ@Disabled ×¢½âÒ²ÊÇͨ¹ýÕâÑùµÄ»úÖÆÀ´ÊµÏֵġ£ContainerExecutionCondition
½Ó¿Ú¶ÔÓ¦µÄÊDzâÊÔÀ࣬¶ø TestExecutionCondition ½Ó¿Ú¶ÔÓ¦µÄÊDzâÊÔ·½·¨¡£
ContainerExecutionCondition ½Ó¿ÚµÄ evaluate ·½·¨½ÓÊÜ ContainerExtensionContext
½Ó¿Ú×÷Ϊ²ÎÊý£¬²¢·µ»Ø ConditionEvaluationResult ÀàµÄ¶ÔÏó×÷Ϊ½á¹û¡£Í¨¹ý ContainerExtensionContext
½Ó¿Ú¿ÉÒÔ»ñÈ¡µ½µ±Ç°²âÊÔÀàµÄÉÏÏÂÎÄÐÅÏ¢£¬¶ø ConditionEvaluationResult ÀàÔò±íʾ¸Ã²âÊÔÀàÊÇ·ñ±»ÆôÓá£
TestExecutionCondition ½Ó¿ÚÒ²Êǰüº¬Ò»¸ö evaluate ·½·¨£¬Ö»²»¹ý²ÎÊýÀàÐÍÊÇ
TestExtensionContext£¬Æä·µ»Ø½á¹ûÒ²ÊÇ ConditionEvaluationResult
ÀàµÄ¶ÔÏó¡£
ͨ¹ýÀ©Õ¹µÄ·½Ê½½ûÓõIJâÊÔÀàºÍ·½·¨£¬¿ÉÒÔͨ¹ý JVM ²ÎÊý junit.conditions.deactivate
À´ÖØÐÂÆôÓã¬Ö»ÐèÒª°ÑÏàÓ¦µÄÌõ¼þÀà½ûÓü´¿É¡£
Çåµ¥ 18 ÖÐÀ©Õ¹ DisableAPITests ʵÏÖÁË ContainerExecutionCondition
ºÍ TestExecutionCondition ½Ó¿Ú£¬µ±²âÊÔÀà»ò·½·¨Öаüº¬±êÇ© api ʱ£¬Í¨¹ý ConditionEvaluationResult.disabled()±íʾ¶ÔÆä½ûÓá£
Çåµ¥ 18. ²âÊÔÖ´ÐÐÌõ¼þÀ©Õ¹Ê¾Àý
public class DisableAPITests implements ContainerExecutionCondition, TestExecutionCondition { @Override public ConditionEvaluationResult evaluate (final ContainerExtensionContext context) { return checkTags(context.getTags()); } @Override public ConditionEvaluationResult evaluate (final TestExtensionContext context) { return checkTags(context.getTags()); } private ConditionEvaluationResult checkTags (final Set<String> tags) { if (tags.contains("api")) { return ConditionEvaluationResult.disabled("No API tests!"); } return ConditionEvaluationResult.enabled(""); } } |
Çåµ¥ 19 ÖеIJâÊÔÀàµÄ simpleAPITest ·½·¨Ê¹ÓÃÁ˱êÇ© api£¬ÔÚÖ´ÐÐʱ»á±»½ûÓá£
Çåµ¥ 19. ʹÓà DisableAPITests µÄ²âÊÔÓÃÀý
@ExtendWith(DisableAPITests.class) public class APITests { @Test @Tag("api") public void simpleAPITest() { System.out.println("simple API test"); } } |
ºó´¦Àí²âÊÔʵÀý
ͨ¹ý TestInstancePostProcessor ¿ÉÒÔ¶Ô²âÊÔʵÀýÌí¼Óºó´¦ÀíµÄÂß¼£¬´Ó¶ø½øÒ»²½¶ÔʵÀý½øÐж¨ÖÆ£¬±ÈÈç¿ÉÒÔͨ¹ýÒÀÀµ×¢ÈëµÄ·½Ê½À´ÉèÖÃÆäÖеÄÊôÐÔ£¬»òÊÇÌí¼Ó¶îÍâµÄ³õʼ»¯Âß¼µÈ¡£
ÔÚÇåµ¥ 20 ÖУ¬À©Õ¹ InjectAPIEnv ʵÏÖÁË TestInstancePostProcessor
½Ó¿Ú£¬ÔÚ postProcessTestInstance ·½·¨ÖÐͨ¹ý Commons Lang ÖÐµÄ MethodUtils.invokeMethod
À´µ÷Óõ±Ç°²âÊÔʵÀýÖÐµÄ setEnv ·½·¨£¬²¢ÉèÖÃΪ DEV¡£
Çåµ¥ 20. ºó´¦Àí²âÊÔʵÀýµÄʾÀý
public class InjectAPIEnv implements TestInstancePostProcessor { @Override public void postProcessTestInstance (final Object testInstance, final ExtensionContext context) throws Exception { MethodUtils.invokeMethod(testInstance, "setEnv", "DEV"); } } |
Çåµ¥ 21 Öиø³öÁËʹÓøÃÀ©Õ¹µÄʾÀý¡£
Çåµ¥ 21. ʹÓúó´¦Àí²âÊÔʵÀýµÄʾÀý
@ExtendWith(InjectAPIEnv.class) public class APITests { private String env; public void setEnv(final String env) { this.env = env; } @Test public void showInjected() { assertEquals("DEV", this.env); } } |
²ÎÊý½âÎö
ÔÚ֮ǰ½éÉÜ JUnit 5 µÄ²ÎÊý½âÎöʱ£¬Ìáµ½ÁË JUnit 5 ¿ÉÒÔ×Ô¶¯½âÎö TestInfo ºÍ TestReporter
ÀàÐ͵IJÎÊý¡£³ýÁËÕâÁ½ÖÖÀàÐ͵IJÎÊýÖ®Í⣬Ҳ¿ÉÒÔͨ¹ýÀ©Õ¹ ParameterResolver ½Ó¿ÚÀ´Ìṩ×Ô¶¨ÒåµÄ²ÎÊý½âÎö¹¦ÄÜ¡£ParameterResolver
½Ó¿ÚÖÐÓÐÁ½¸ö·½·¨£¬·Ö±ðÊÇ supports ºÍ resolve¡£Á½¸ö·½·¨µÄ²ÎÊýÊÇÒ»ÑùµÄ£¬·Ö±ðÊÇ ParameterContext
ºÍ ExtensionContext ½Ó¿ÚµÄ¶ÔÏó¡£Í¨¹ý ParameterContext ¿ÉÒÔ»ñÈ¡µ½ÐèÒª½âÎöµÄ²ÎÊýµÄÐÅÏ¢£¬¶ø
ExtensionContext ½Ó¿Ú¿ÉÒÔ»ñÈ¡µ½µ±Ç°²âÊÔÀà»ò·½·¨µÄÉÏÏÂÎÄÐÅÏ¢¡£
Çåµ¥ 22. ²ÎÊý½âÎöµÄʾÀý
public class APIEnvResolver implements ParameterResolver { @Override public boolean supports (final ParameterContext parameterContext, final ExtensionContext extensionContext) throws ParameterResolutionException { return parameterContext.getParameter().getType() == String.class && parameterContext.getIndex() == 0; } @Override public Object resolve(final ParameterContext parameterContext, ? final ExtensionContext extensionContext) throws ParameterResolutionException { return "DEV"; } } |
Çåµ¥ 23 ¸ø³öÁËʹÓòÎÊý½âÎöÀ©Õ¹µÄʾÀý¡£
Çåµ¥ 23. ʹÓòÎÊý½âÎöÀ©Õ¹µÄʾÀý
@ExtendWith(APIEnvResolver.class) public class APITests { @Test public void showResolved(final String env) { assertEquals("DEV", env); } } |
²âÊÔÖ´Ðлص÷·½·¨
JUnit 5 ÌṩÁËһϵÁÐÓë²âÊÔÖ´Ðйý³ÌÏà¹ØµÄ»Øµ÷·½·¨£¬ÔÚ²âÊÔÖ´ÐÐÖеIJ»Í¬½×¶Î£¬ÔËÐÐ×Ô¶¨ÒåµÄÂß¼¡£ÕâЩ»Øµ÷·½·¨¿ÉÒÔÓÃÀ´×öһЩÓëÈÕÖ¾ºÍÐÔÄÜ·ÖÎöµÄÈÎÎñ¡£¾ßÌåµÄ»Øµ÷·½·¨ºÍÃèÊö¼û±í
3¡£
±í 3. ²âÊÔÖ´ÐÐÖеĻص÷·½·¨

Çåµ¥ 24 Öиø³öÁËʹÓòâÊÔÖ´ÐÐÖеĻص÷·½·¨µÄʾÀý¡£
Çåµ¥ 24. ʹÓòâÊÔÖ´Ðлص÷·½·¨µÄʾÀý
public class Timing implements BeforeTestExecutionCallback, AfterTestExecutionCallback { @Override public void beforeTestExecution (final TestExtensionContext context) throws Exception { getStore(context).put (context.getTestMethod().get(), System.currentTimeMillis()); } @Override public void afterTestExecution (final TestExtensionContext context) throws Exception { final Method testMethod = context.getTestMethod().get(); final long start = getStore(context).remove(testMethod, long.class); final long duration = System.currentTimeMillis() - start; context.publishReportEntry(ImmutableMap.of (testMethod.getName(), Long.toString(duration))); } private Store getStore(TestExtensionContext context) { return context.getStore(Namespace.create(getClass(), context)); } } |
Òì³£´¦Àí
ͨ¹ý TestExecutionExceptionHandler ½Ó¿Ú¿ÉÒÔ¶Ô²âÊÔÔËÐÐÖÐÅ׳öµÄÒì³£½øÐд¦Àí¡£¿ÉÒÔÔÚÔËÐÐÖкöÂÔijЩÒì³££¬»òÊÇÔÚÌØ¶¨ÀàÐ͵ÄÒì³£·¢ÉúʱִÐÐijЩ´¦Àí¶¯×÷£¬Èç¿ÉÒÔÔÚ³öÏÖÊý¾Ý¿âÒ쳣ʱ»Ø¹öÊÂÎñ¡£Çåµ¥
25 ¸ø³öÁËÒì³£´¦ÀíµÄʾÀý¡£
Çåµ¥ 25. Òì³£´¦ÀíµÄʾÀý
public class IgnoreNullPointerException implements TestExecutionExceptionHandler { @Override public void handleTestExecutionException (final TestExtensionContext context, final Throwable throwable) throws Throwable { if (throwable instanceof NullPointerException) { return; } throw throwable; } } |
Ç¨ÒÆÖ¸ÄÏ
JUnit ƽ̨¿ÉÒÔͨ¹ý Jupiter ÒýÇæÀ´ÔËÐÐ JUnit 5 ²âÊÔ£¬Vintage ÒýÇæÀ´ÔËÐÐ
JUnit 3 ºÍ JUnit 4 ²âÊÔ¡£Òò´Ë£¬ÒÑÓÐµÄ JUnit 3 ºÍ 4 µÄ²âÊÔ²»ÐèÒªÈκÎÐ޸ľͿÉÒÔÖ±½ÓÔÚ
JUnit ƽ̨ÉÏÔËÐС£Ö»ÐèҪȷ±£ Vintage ÒýÇæµÄ jar °ü³öÏÖÔÚ classpath ÖУ¬JUnit
ƽ̨»á×Ô¶¯·¢ÏÖ²¢Ê¹ÓøÃÒýÇæÀ´ÔËÐÐ JUnit 3 ºÍ 4 ²âÊÔ¡£¿ª·¢ÈËÔ±¿ÉÒÔ°´ÕÕ×Ô¼ºµÄÏîÄ¿°²ÅÅÀ´¹æ»®Ç¨ÒƵ½
JUnit 5 µÄ½ø¶È¡£¿ÉÒÔ±£³ÖÒÑÓÐµÄ JUnit 3 ºÍ 4 µÄ²âÊÔÓÃÀý²»±ä£¬¶øÐÂÔö¼ÓµÄ²âÊÔÓÃÀýÔòʹÓÃ
JUnit 5¡£
ÔÚ½øÐÐÇ¨ÒÆµÄʱºòÐèҪעÒâÈçϵı仯£º
×¢½âÔÚ org.junit.jupiter.api °üÖУ¬¶ÏÑÔÔÚ org.junit.jupiter.api.Assertions
ÀàÖУ¬Ç°ÖÃÌõ¼þÔÚ org.junit.jupiter.api.Assumptions ÀàÖС£
°Ñ@Before ºÍ@After Ìæ»»³É@BeforeEach ºÍ@AfterEach¡£
°Ñ@BeforeClass ºÍ@AfterClass Ìæ»»³É@BeforeAll ºÍ@AfterAll¡£
°Ñ@Ignore Ìæ»»³É@Disabled¡£
°Ñ@Category Ìæ»»³É@Tag¡£
°Ñ@RunWith¡¢@Rule ºÍ@ClassRule Ìæ»»³É@ExtendWith¡£
С½á
µ¥Ôª²âÊÔÊÇÓ¦ÓóÌÐò²»¿É»òȱµÄÒ»²¿·Ö¡£×÷Ϊ Java ¿ª·¢Öе¥Ôª²âÊÔµÄÊÂʵ±ê×¼£¬JUnit ±»¹ã·ºÊ¹Óᣱ¾ÎÄÏêϸ½éÉÜÁËÔÚ
JUnit 5 ÖбàдºÍÔËÐвâÊÔÓÃÀýµÄ·½Ê½£¬²¢¶ÔеÄÀ©Õ¹»úÖÆ×öÁËÏêϸ½éÉÜ¡£ÔÚ±àд²âÊÔÓÃÀý·½Ã棬±¾ÎĽéÉÜÁË
JUnit 5 ÖÐеÄ×¢½â¡¢¶ÏÑÔºÍǰÖÃÌõ¼þ£¬ÒÔ¼°¶ÔÓÚǶÌײâÊÔ¡¢ÒÀÀµ×¢ÈëºÍ¶¯Ì¬²âÊÔµÄÖ§³Ö¡£ÔÚÔËÐвâÊÔÓÃÀý·½Ã棬Ïêϸ½éÉÜÁËͨ¹ý
Gradle¡¢Maven ºÍÃüÁîÐÐÀ´ÔËÐÐ JUnit 5 ²âÊÔ¡£À©Õ¹»úÖÆ×÷Ϊ JUnit 5 µÄÒ»´óÁÁµã£¬±¾ÎÄÏêϸ½éÉÜÁËÈçºÎͨ¹ýÀ©Õ¹À´Ìí¼Ó²âÊÔÖ´ÐÐÌõ¼þ¡¢ºó´¦Àí²âÊÔʵÀý¡¢½âÎö²âÊԺʹ¦ÀíÒì³£µÈ¡£¿ª·¢ÈËÔ±¿ÉÒÔÏÖÔھͳ¢ÊÔ
JUnit 5 ÖеÄй¦ÄÜ¡£ |