如何使用JUnit的测试引擎正确地运行扩展测试?

3zwjbxry  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(155)

我编写了一个JUnit扩展,它在执行测试后生成一些报告。
我想做一个测试用例来确保扩展按预期工作,结果发现:
How to test JUnit Jupiter (JUnit 5) Extensions
按照指南,我设法达到了我的测试正在工作的程度,但“不可靠”,因为ExampleExtensionTest执行了两次-一次作为主要junit执行(gradle test)的一部分,一次作为extensionShouldGenerateReport()测试用例的一部分。
根据JUnit的文档,我可以将static class ExampleExtensionTest更改为class ExampleExtensionTest,JUnit不会拾取它。问题是,它在extensionShouldGenerateReport()中也不会拾取!
看起来我好像漏掉了什么,但我似乎想不出来。
下面是我的测试案例:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor;
import org.junit.platform.testkit.engine.EngineExecutionResults;
import org.junit.platform.testkit.engine.EngineTestKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Path;

import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;

public class ExtensionTest
{

    private final Logger logger = LoggerFactory.getLogger(ExtensionTest.class);

    @Test
    public void extensionShouldGenerateReport() throws IOException
    {

        Path reportPath = Path.of("build/tmp/example-recorded-test");
        logger.info("Configured report path: {}", reportPath);

        EngineTestKit.engine(JupiterEngineDescriptor.ENGINE_ID)
                     .selectors(selectClass(ExtensionTest.ExampleExtensionTest.class))
                     .execute()
                     .containerEvents()
                     .assertStatistics(stats -> stats.started(1).succeeded(1));

        // Assert all files were generated.
        assertThat(reportPath.toFile().exists()).isTrue();
        assertThat(reportPath.resolve("index.html").toFile().exists()).isTrue();
        assertThat(reportPath.resolve("metadata.json").toFile().exists()).isTrue();

    }

    @ExtendWith(MyExtension.class)
    static class ExampleExtensionTest
    {
        @MyAnnotation(reportPath = "build/tmp/example-recorded-test")
        public void test()
        {
            return; // noop.
        }
    }

}
eeq64g8w

eeq64g8w1#

在这个问题上浪费了几个小时之后,我找到了解决这个问题的方法。
最简单和最不具侵入性的方法是在ExampleExtensionTest上使用@EnabledIfSystemProperty(name = "some-property")注解。
代码如下:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor;
import org.junit.platform.testkit.engine.EngineExecutionResults;
import org.junit.platform.testkit.engine.EngineTestKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Path;

import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;

public class ExtensionTest
{

    private final Logger logger = LoggerFactory.getLogger(ExtensionTest.class);

    @BeforeAll
    public static void beforeAll()
    {
        System.setProperty("my-property", "true");
    }

    @AfterAll
    public static void afterAll()
    {
        System.clearProperty("my-property");
    }

    @Test
    public void extensionShouldGenerateReport() throws IOException
    {

        Path reportPath = Path.of("build/tmp/example-recorded-test");
        logger.info("Configured report path: {}", reportPath);

        EngineTestKit.engine(JupiterEngineDescriptor.ENGINE_ID)
                     .selectors(selectClass(ExtensionTest.ExampleExtensionTest.class))
                     .execute()
                     .containerEvents()
                     .assertStatistics(stats -> stats.started(1).succeeded(1));

        // Assert all files were generated.
        assertThat(reportPath.toFile().exists()).isTrue();
        assertThat(reportPath.resolve("index.html").toFile().exists()).isTrue();
        assertThat(reportPath.resolve("metadata.json").toFile().exists()).isTrue();

    }

    @ExtendWith(MyExtension.class)
    @EnabledIfSystemProperty(named = "my-property", matches = "true")
    static class ExampleExtensionTest
    {
        @MyAnnotation(reportPath = "build/tmp/example-recorded-test")
        public void test()
        {
            return; // noop.
        }
    }

}

这将导致测试被排除在全局运行之外,但当通过EngineTestKit以编程方式调用它时,它仍然工作。

相关问题