在JUnit 5中正确设置(系统)属性

时间:2017-10-20 09:48:29

标签: java junit junit5

我们正在使用类似于System Rules的方法来处理JUnit 4测试中的(系统)属性。这样做的主要原因是每次测试后都要清理环境,这样其他测试就不会无意中依赖于可能的副作用。

自JUnit 5发布以来,我想知道是否有“JUnit 5方式”这样做?

3 个答案:

答案 0 :(得分:6)

您可以使用extension API。您可以创建一个注释,用于定义测试方法的扩展。

import org.junit.jupiter.api.extension.ExtendWith;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ExtendWith(SystemPropertyExtension.class)
public @interface SystemProperty {

    String key();

    String value();
}

然后,您可以创建扩展类:

import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;

public class SystemPropertyExtension implements AfterEachCallback, BeforeEachCallback {

    @Override
    public void afterEach(ExtensionContext extensionContext) throws Exception {
        SystemProperty annotation = extensionContext.getTestMethod().get().getAnnotation(SystemProperty.class);
        System.clearProperty(annotation.key());
    }

    @Override
    public void beforeEach(ExtensionContext extensionContext) throws Exception {
        SystemProperty annotation = extensionContext.getTestMethod().get().getAnnotation(SystemProperty.class);
        System.setProperty(annotation.key(), annotation.value());
    }
}

最后,您可以使用属性注释您的测试:

@Test
@SystemProperty(key = "key", value = "value")
void testPropertey() {
    System.out.println(System.getProperty("key"));
}

此解决方案仅支持每个测试的一个系统属性。如果要支持多个测试,可以使用嵌套注释,扩展也可以处理:

@Test
@SystemProperties({
    @SystemProperty(key = "key1", value = "value"),
    @SystemProperty(key = "key2", value = "value")
})
void testPropertey() {
    System.out.println(System.getProperty("key1"));
    System.out.println(System.getProperty("key2"));
}

答案 1 :(得分:6)

JUnit Pioneer,一个“ JUnit 5扩展包”。它带有@ClearSystemProperty@SetSystemProperty。来自docs

@ClearSystemProperty@SetSystemProperty批注可分别用于清除设置测试执行的系统属性的值。这两个注释均在测试方法和类级别上起作用,并且可重复且可组合。执行带注释的方法后,注释中提到的属性将恢复为其原始值,或者如果以前没有属性,则将其清除。 在测试过程中更改的其他系统属性,不会被恢复。

示例:

@Test
@ClearSystemProperty(key = "some key")
@SetSystemProperty(key = "another key", value = "new value")
void test() {
    assertNull(System.getProperty("some key"));
    assertEquals("new value", System.getProperty("another key"));
}

答案 2 :(得分:0)

JUnit Pioneer方式要求在编译时知道系统属性。在运行时生成它们的地方,例如通过TestcontainersWiremock在随机端口上创建事物,最好使用可以由动态值驱动的事物。

可以使用提供JUnit 5的系统存根https://github.com/webcompere/system-stubs来解决该问题,该系统存根是系统Lambda的代码的分支,该代码本身由系统规则的作者构建。

@ExtendWith(SystemStubsExtension.class)
class SomeTest {
    // can be initialised here with some up front properties
    // or leave like this for auto initialization
    @SystemStub
    private SystemProperties someProperties;

    @BeforeEach
    void beforeEach() {
        someProperties.set("prop1", "value1")
            .set("prop2", "value2");
    }

    @Test
    void someTest() {
        // properties are set here
        // and can also call System.setProperty


        // properties reset to state before the test case ran
        // as the test case is tidied up
    }
}