Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Migrating to JUnit 5
Search
LINE Developers Taiwan
PRO
October 21, 2020
Technology
3.7k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Migrating to JUnit 5
by Joanna Hu at TWJUG 20201021
https://twjug.kktix.cc/events/twjug202010
LINE Developers Taiwan
PRO
October 21, 2020
More Decks by LINE Developers Taiwan
See All by LINE Developers Taiwan
Zona Codex Community Meetup 分享
line_developers_tw
PRO
0
1.2k
Evan & Zona COSCUP 2026 分享
line_developers_tw
PRO
0
170
台大資管營企業參訪-Bowen Chen
line_developers_tw
PRO
0
80
2026TECHFRESH畢業分享會 - AI 時代的人生存檔點
line_developers_tw
PRO
0
3.1k
2026TECHFRESH畢業分享會 - 原生還是跨平台? App 開發踩坑實錄
line_developers_tw
PRO
0
3.1k
2026TECHFRESH畢業分享會 - 葬送的通靈師:化系統與用戶雜訊成行動訊號
line_developers_tw
PRO
0
3.1k
2026 TECHFRESH 畢業分享會 - AI-Native 重塑軟體工程與虛擬講師
line_developers_tw
PRO
0
3.1k
2026 TECHFRESH 畢業分享會 - 開發日常大解密!從領域驅動到企業級上線
line_developers_tw
PRO
0
3.1k
2026TECHFRESH畢業分享會 - Lightning Talk - E起 See See : 電商推薦讀心術? 數據說了算
line_developers_tw
PRO
0
3.1k
Other Decks in Technology
See All in Technology
全社に広がるMCPサーバーを、 どう安全に管理するか MCPass開発の舞台裏
mtpooh
3
220
名刺メーカーDevグループ 紹介資料
sansan33
PRO
0
1.3k
[RSJ26] Building a VLA Model Based on Self-Distilled Classification
keio_smilab
PRO
0
110
分割40%キーボードにスムーズに入門するには
hoto17296
1
210
The Django UUID Story - DjangoCon US 2026
pauloxnet
0
360
AI × Datadog MCP でコスト削減まで実現した Metric Streams の導入
three_mouth_ago
0
130
サービス内で複数のOP・ASを連鎖させる(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
420
アクセスキー流出時の対応で再認識した攻撃側と防御側の非対称性について
kazzpapa3
1
500
20260903 Tokyo Jazug Night #62 | Azure エンジニアよ、 その環境は本当にセキュアか?
olivia_0707
0
140
会計事務所と顧問先の契約関係をOIDC・OAuthで表現する
terara
0
560
Kiro5兄弟のいまどきのセキュリティ基礎知識
kentapapa
0
460
Genie Code ワークショップ 基礎編 / Genie-Code-Workshop-fundamental
databricksjapan
PRO
0
240
Featured
See All Featured
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Mind Mapping
helmedeiros
PRO
1
340
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
240
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
410
Building the Perfect Custom Keyboard
takai
2
860
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
What's in a price? How to price your products and services
michaelherold
247
13k
Un-Boring Meetings
codingconduct
0
400
Writing Fast Ruby
sferik
630
63k
Transcript
0LJUDWLQJWR -8QLW -RDQQD+X
About the Speaker Joanna Hu • Backend Engineer • Working
in LINE Taiwan since 2019
01 02 03 Summary :KDWLV-8QLW :K\PLJUDWLQJWR-8QLW +RZWRPLJUDWHWR-8QLW
:KDWLV-8QLW • -8QLW-XSLWHUWKHQHZSURJUDPPLQJH[WHQVLRQPRGHOIRUZULWLQJWHVWVDQGH[WHQVLRQVLQ-8QLW • -8QLW9LQWDJH 7HVW(QJLQH IRUUXQQLQJ-8QLWDQG-8QLWEDVHGWHVWVRQWKHSODWIRUP • -8QLW3ODWIRUP IRXQGDWLRQIRUODXQFKLQJWHVWLQJIUDPHZRUNVRQWKH-90
※Source from︓https://dzone.com/articles/7-reasons-to-consider-junit-5
:K\PLJUDWLQJWR-8QLW • 6XSSRUWHGLQPDMRU,'(%XLOGWRROV • ,QWHOOLM ,'($(FOLSVH96&RGH • 0DYHQ*UDGOH • (DV\PLJUDWLRQ
• -8QLWWHVWVFDQFRH[LVWZLWK-8QLWWHVWV • :HFDQXVHERWK-8QLW$VVHUW- DVVHUWLRQVLQRQHWHVW • 1HZ)HDWXUHV
-8QLW1HZ)HDWXUHV • 1HVWHGWHVWV • 'LVSOD\QDPH • 3DUDPHWHUL]HGWHVWV • 0XOWLSOH5XQQHUV •
%HWWHU$VVHUWLRQV EXWZHUHFRPPHQG$VVHUW- LQVWHDG
1HVWHGWHVWV • #1HVWHGFDQKDYHPXOWLSOHOHYHOV • 6XSSRUWQRQVWDWLFLQQHUFODVV class TestingAStackDemo { Stack<Object> stack;
@Test void isInstantiatedWithNew() { new Stack<>(); } @Nested class WhenNew { @BeforeEach void createNewStack() { stack = new Stack<>(); } @Test void isEmpty() { assertTrue(stack.isEmpty()); } @Test void throwsExceptionWhenPopped() { assertThrows(EmptyStackException.class, stack::pop); } @Nested class AfterPushing { // more tests... } } }
1HVWHGWHVWV
'LVSOD\QDPHV • $GG#'LVSOD\1DPH DQQRWDWLRQ • 6XSSRUWDGGLQJRQFODVVPHWKRG @DisplayName("A stack") class TestingAStackDemo
{ Stack<Object> stack; @Test @DisplayName("is instantiated with new Stack()") void isInstantiatedWithNew() { new Stack<>(); } @Nested @DisplayName("when new") class WhenNew { @BeforeEach void createNewStack() { stack = new Stack<>(); } @Test @DisplayName("is empty") void isEmpty() { assertTrue(stack.isEmpty()); } @Nested @DisplayName("after pushing an element") class AfterPushing { // more tests... } } }
'LVSOD\QDPHV • $GG#'LVSOD\1DPH DQQRWDWLRQ • 6XSSRUWDGGLQJRQFODVVPHWKRG
3DUDPHWHUL]HGWHVWV -8QLW class CalculatorJUnit5Test { @ParameterizedTest @ValueSource(strings = { "",
" ", " " }) void isBlank_ShouldReturnTrueForBlankStrings(String input) { assertThat(StringUtils.isBlank(input)).isTrue(); } @ParameterizedTest @NullSource void isBlank_ShouldReturnTrueForNullStrings(String input) { assertThat(StringUtils.isBlank(input)).isTrue(); } @ParameterizedTest @CsvSource({ "0,0,0", "1,1,2" }) void add(int first, int second, int expected) { final Calculator calculator = new Calculator(); final int result = calculator.add(first, second); assertThat(result).isEqualTo(expected); } }
0XOWLSOH5XQQHUV -8QLWRQO\VXSSRUWVVLQJOHUXQQHUZKLOH-8QLWVXSSRUWVPXOWLSOHH[WHQVLRQV // JUnit 4 @RunWith(MockitoJUnitRunner.class) public class CMSProductServiceTest {
// ... } // JUnit 5 @ExtendWith({ MockitoExtension.class, SoftAssertionsExtension.class }) public class CMSProductServiceTest { // ... }
+RZWRPLJUDWHWR-8QLW • 8SJUDGHWR-8QLWLQ0DYHQ*UDGOH • 8SJUDGH0DYHQWR 2U0DYHQVXUHILUHIDLOVDIHSOXJLQWR • 8SJUDGH*UDGOHWR • :ULWHQHZWHVWVLQ-8QLW
• 0LJUDWHH[LVWLQJ-8QLWWHVWV • 5HZULWH-8QLW5XOHWR-8QLW([WHQVLRQ LIDQ\
0LJUDWHH[LVWLQJ-8QLWWHVWV JUnit 4 JUnit 5 org.junit.Test org.junit.jupiter.api.Test org.junit.Before org.junit.jupiter.api.BeforeEach org.junit.After
org.junit.jupiter.api.AfterEach org.junit.BeforeClass org.junit.jupiter.api.BeforeAll org.junit.AfterClass org.junit.jupiter.api.AfterAll org.junit.Ignore org.junit.jupiter.api.Disabled org.junit.Assert org.junit.jupiter.api.Assertions (we use AssertJ) org.junit.Assert.assertThat org.hamcrest.MatcherAssert.assertThat org.junit.runner.RunWith org.junit.jupiter.api.extension.ExtendWith org.mockito.junit.MockitoJUnitRunner org.mockito.junit.jupiter.MockitoExtension org.springframework.test.context.junit4.SpringRu nner org.springframework.test.context.junit.jupiter.Spri ngExtension
5HZULWH-8QLW5XOHWR-8QLW([WHQVLRQ -8QLW5XOH public class EmbeddedMySqlRule extends ExternalResource { private EmbeddedMysql
embeddedMysql; @Override protected void before() { // ... embeddedMysql = EmbeddedMysql.anEmbeddedMysql(config, downloadConfig) .addSchema("ecac", ScriptResolver.classPathScript("db/setup.sql")) .start(); } @Override protected void after() { if (embeddedMysql != null) { embeddedMysql.stop(); } } }
5HZULWH-8QLW5XOHWR-8QLW([WHQVLRQ -8QLW([WHQVLRQ public class EmbeddedMySqlExtension implements AfterAllCallback, BeforeAllCallback { private
EmbeddedMysql embeddedMysql; @Override public void beforeAll(ExtensionContext extensionContext) throws Exception { // ... embeddedMysql = EmbeddedMysql.anEmbeddedMysql(config, downloadConfig) .addSchema("ecac", ScriptResolver.classPathScript("db/setup.sql")) .start(); } @Override public void afterAll(ExtensionContext extensionContext) throws Exception { if (embeddedMysql != null) { embeddedMysql.stop(); } } }
0LJUDWH8VLQJ,QWHOOL-,'($ 0LJUDWHRQHWHVW 0LJUDWHDOOWHVWV 5HIDFWRU!0LJUDWH https://blog.jetbrains.com/idea/2020/08/migrating-from-junit-4-to-junit-5/
• -8QLWZHEVLWHhttps://junit.org/junit5/ • 5HDVRQVWR&RQVLGHU-8QLWhttps://dzone.com/articles/7-reasons-to-consider-junit-5 • 0LJUDWLQJIURP-8QLWWR-8QLWhttps://blog.jetbrains.com/idea/2020/08/migrating-from-junit-4-to-junit-5/ 5HIHUHQFHV
THANK YOU