Scoped System Properties JUnit Extension

JUnit 5 Extension to isolate changes to system properties per test

License

License

Categories

Categories

JUnit Unit Testing
GroupId

GroupId

io.github.bmuskalla
ArtifactId

ArtifactId

scoped-system-properties-junit
Last Version

Last Version

1.1.0
Release Date

Release Date

Type

Type

module
Description

Description

Scoped System Properties JUnit Extension
JUnit 5 Extension to isolate changes to system properties per test
Project URL

Project URL

https://github.com/bmuskalla/scoped-system-properties
Source Code Management

Source Code Management

https://github.com/bmuskalla/scoped-system-properties

Download scoped-system-properties-junit

Dependencies

runtime (2)

Group / Artifact Type Version
io.github.bmuskalla : scoped-system-properties jar 1.1.0
org.junit.jupiter : junit-jupiter-api jar

Project Modules

There are no modules declared in this project.

Scoped System Properties

Build

tldr;

Easy to use, lock-free, thread-safe scoped system properties to isolate changes to global state.

Motivation

If you need to change system properties for specific calls to 3rd party APIs, you could just use a try/finally construct. The downside is that you need to ensure that no other code in parallel tries to read/write the same system properties. Other folks use a global lock to around the try/finally to avoid any other thread in the system to see this particular state.

While generally, your code should abstract away access to global state like system properties, 3rd party code you use may not do that. Too many libraries rely on specific system properties for configuration or feature toggles.

This library helps to deal with those 3rd party dependencies that require the usage of system properties by isolating access and mutation to said system properties.

Library

Gradle

Groovy

implementation 'io.github.bmuskalla:scoped-system-properties:1.1.0'

Kotlin

implementation("io.github.bmuskalla:scoped-system-properties:1.1.0")

Maven

<dependency>
    <groupId>io.github.bmuskalla</groupId>
    <artifactId>scoped-system-properties</artifactId>
    <version>1.1.0</version>
</dependency>

Example (as library)

System.setProperty("someKey", "global value");
try (PropertyEnvironment env = ScopedSystemProperties.newPropertyEnvironment()) {
    env.setProperty("someKey", "scopedValue");
    // or using the usual Java APIs
    // System.setProperty("someKey", "scopedValue");

    System.getProperty("someKey"); // = "scopedValue"

    // another thread calling System.getProperty("someKey") will see `global value`
}
System.getProperty("someKey") // = "global value"

JUnit 5 Extension

Gradle

Groovy

implementation 'io.github.bmuskalla:scoped-system-properties-junit:1.1.0'

Kotlin

implementation("io.github.bmuskalla:scoped-system-properties-junit:1.1.0")

Maven

<dependency>
    <groupId>io.github.bmuskalla</groupId>
    <artifactId>scoped-system-properties-junit</artifactId>
    <version>1.1.0</version>
</dependency>

Example (in JUnit Jupiter)

@BeforeEach
void setUp() {
    assertEquals("baseline", System.getProperty("key"));
    System.setProperty("key", "before");
}

@Test
@IsolatedSystemProperties
void setsValueInTest() throws Exception {
    assertEquals("before", System.getProperty("key"));
    System.setProperty("key", "other");
}

@AfterAll
static void tearDown() {
    assertEquals("baseline", System.getProperty("key"));		
}

@IsolatedSystemProperties can be used on individual test methods or on the whole test class. In both cases, the individual test (and the respective lifecycle methods like @BeforeEach) will be isolated against the rest of the environment.

Alternative approach using JUnit

Proper isolation can be achieved by leveraging a global lock using JUnits @ResourceLock (see Synchronization when running Parallel Tests). While this has the same effect of avoiding race conditions on the system properties, such tests cannot be run in parallel if they require mutating access to system properties.

Changelog

1.1.0

  • Avoid global changes to affect the isolated environment
  • Support all Properties API
  • Simplified delegation

1.0.0 Reworked API

  • Favor PropertyEnvironment as concept

0.5.0 Initial release

  • Support as standalone library
  • Support as JUnit 5 extension

Versions

Version
1.1.0
1.0.0
0.5.0