簡體   English   中英

JUnit5:Suite 方法調用前后

[英]JUnit5: Before and After Suite method invocation

我花了幾天時間尋找解決方案,所以我知道所有基本答案

我看過文檔,我知道,@BeforeClass/@AfterClass 被@BeforeAll/@AfterAll 替換了,@RunWith 不再存在; 被@ExtendWith取代我已經閱讀了stackoverflow上的所有主題(刪除鏈接,因為stackoverflow假裝它是垃圾郵件:(

我曾經在套件中運行一些 JUnit4 測試。 每個 Suite class Suite1.class、Suite2.class都有幾個@Test方法, @BeforeClass/@AfterClass所有測試方法之前/之后運行。

@RunWith(StopOnFailureSuite.class)
@Suite.SuiteClasses({
        Test1.class,
        Test2.class
})

public class TSuite_20 {
    private static final byte SUITE_NUMBER = 20;

    @BeforeClass
    public static void setUpClass() {
        //some logic for suite setup
    }

    @AfterClass
    public static void tearDownClass() {
        //some logic for teardown
    }
}

因為我想使用 @ParameterizedTests,所以我需要遷移到 JUnit5。 突然我意識到,完全相同的行為,曾經在 JUnit4 中是不可能實現的。 [運行一些自定義設置代碼; 運行多個測試類,其中可能包含多個@Test 方法; 運行一些自定義的拆卸代碼];

有沒有人知道(最好有例子)用 JUnit 5 制作它的方法?

選項 1此代碼永遠不會執行BeforeAfterSuite#beforeAllBeforeAfterSuite#afterAll

@ExtendWith(BeforeAfterSuite.class)
@Suite
@SelectClasses({
        Test1.class,
        Test2.class
})
public class TSuite_20 {
    public static final byte SUITE_NUMBER = 20;
}

public class BeforeAfterSuite implements BeforeAllCallback, AfterAllCallback
/*,TestInstancePreConstructCallback, BeforeTestExecutionCallback, 
AfterTestExecutionCallback, ExtensionContext.Store.CloseableResource*/ {
    private static boolean started = false;

    @Override
    public void beforeAll(ExtensionContext context) {
        if (!started) {
            started = true;
            //before stuff
        }
    }

    @Override
    public void afterAll(ExtensionContext context) throws Exception {
        //after all;
    }
}

選項 2我只是好奇,如果我將測試方法放入其中,JUnit 將如何處理套件 class...此代碼將在 TSuite_20#test 之前和之后執行一次BeforeAfterSuite#beforeAllBeforeAfterSuite#afterAll一次

@ExtendWith(BeforeAfterSuite.class)
@Suite
@SelectClasses({
        Test1.class,
        Test2.class
})
public class TSuite_20 {
    public static final byte SUITE_NUMBER = 20;
    
    @Test
    public void test() {
    }
}

選項 3我們還可以為每個測試 class 應用@ExtendWith(BeforeAfterSuite.class) ,這將導致每個測試 class 的BeforeAfterSuite#beforeAllBeforeAfterSuite#afterAll 。(在此示例中 - 2 次)。

@ExtendWith(BeforeAfterSuite.class)
public class Test1 {
    
    @Test
    public void test11() {
    }
    @Test
    public void test12() {
    }
}

@ExtendWith(BeforeAfterSuite.class)
public class Test2 {
    
    @Test
    public void test21() {
    }
    @Test
    public void test22() {
    }
}

選項 4我也試一試

  • 沒有@ExtendWith()@BeforeAll + @AfterAll (正如預期的那樣,什么也沒發生)`
  • 沒有@ExtendWith()@BeforeAll + @Test + @AfterAll (正如預期的那樣,針對特定套件類單獨執行 BeforeAll/AfterAll)`

選項 5聽眾是我實現預期行為的最后希望。 我已經為 LauncherSessionListener 創建了自己的 impl,只是因為我認為它可以讓我在測試開始之前准確地執行 smth。

public class BeforeAfterSuiteLauncher implements LauncherSessionListener {
    private static boolean started = false;
    @Override
    public void launcherSessionOpened(LauncherSession session) {
        if (!started) {
            started = true;
            //before all
        }
    }
    @Override
    public void launcherSessionClosed(LauncherSession session) {
        //after all
    }
}

我還添加了一些默認的 impl CompositeLauncherSessionListener

包結構截圖顯示 Java SPI 配置: LauncherSessionListener

對於 TestExecutionListener,我添加了兩個默認實現,只是為了捕獲至少一個 Listener:

org.junit.platform.launcher.listeners.LoggingListener
org.junit.platform.launcher.listeners.SummaryGeneratingListener

和一個習俗

public class BeforeAfterExecutionListener implements TestExecutionListener {
    @Override
    public void testPlanExecutionStarted(TestPlan testPlan) {
        //before all
    }

    @Override
    public void testPlanExecutionFinished(TestPlan testPlan) {
        //after all
    }
}

包結構截圖顯示 Java SPI 配置: TestExecutionListener

並且只觸發了 SummaryGeneratingListener!

我究竟做錯了什么? 為什么我的 BeforeAfterExecutionListener impl 沒有被加載和觸發?

PS 以上代碼均在Intellij Idea 2021.1.3 旗艦版下執行

java version "1.8.0_341"
Java(TM) SE Runtime Environment (build 1.8.0_341-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.341-b10, mixed mode)

這是 intelliJs 命令:

C:\Tools\jdk\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:61280,suspend=y,server=n -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:C:\Users\userName\AppData\Local\JetBrains\IntelliJIdea2021.1\groovyHotSwap\gragent.jar -javaagent:C:\Users\userName\AppData\Local\JetBrains\IntelliJIdea2021.1\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath C:\Users\userName\AppData\Local\Temp\classpath1705687115.jar com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 com.testdirectly.application.testcase.TSuite_20

結果是JUnit5IdeaTestRunner

我的 gradle 依賴項

dependencies {
        //JUnit platform
        // to group tests by package, by class name, by class name pattern, etc (use @Suite, @SelectClasses) :junit-platform-suite-api:1.9.2
        // and to filter/discover and run them         (SuiteLauncher, SuiteTestEngine, SuiteTestDescriptor) :junit-suite-engine:1.9.2
        testImplementation "org.junit.platform:junit-platform-suite:1.9.2"
        //Launcher, engine discovery
        testImplementation "org.junit.platform:junit-platform-launcher:1.9.2"//to run tests

        //JUnit Jupiter
        //to use assertions and so on
        testImplementation "org.junit.jupiter:junit-jupiter-api:5.9.2"
        //to use @ParameterizedTest
        testImplementation "org.junit.jupiter:junit-jupiter-params:5.9.2"
        //Jupiter engine to run junit5 tests (JupiterTestEngine, Extensions, etc)
        testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.9.2"
}

簡答

如果您稍微調整選項 5,它就會起作用(見下文)。

長答案

選項 1 和 2 不起作用,因為@ExtendWith是 Jupiter 擴展機制,而@Suite觸發它自己的引擎。 測試引擎不結合 JUnit 平台。

選項 4 也是如此,因為@BeforeAll@AfterAll是 Jupiter 注釋。

使選項 5 起作用

首先,我建議使用TestExecutionListener而不是LauncherSessionListener ,因為后者仍處於實驗階段。

因此我們有

package my.project.suites;

import org.junit.platform.launcher.*;

public class BeforeAfterSuiteListener implements TestExecutionListener {

    @Override
    public void testPlanExecutionStarted(TestPlan testPlan) {
        System.out.println("before all");
    }

    @Override
    public void testPlanExecutionFinished(TestPlan testPlan) {
        System.out.println("after all");
    }
}

現在缺少的是您必須全局注冊BeforeAfterSuiteListener 在基於類路徑的 Java 中,您通過資源文件META-INF/services/org.junit.platform.launcher.TestExecutionListener

my.project.suites.BeforeAfterSuiteListener

現在before allafter all應該在每次測試運行時恰好在您的 output 中顯示一次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM