Skip to content

Instantly share code, notes, and snippets.

@beatngu13
Last active June 13, 2020 10:48
Show Gist options
  • Save beatngu13/724a9a78bba61da96566ac5478c2d37b to your computer and use it in GitHub Desktop.
Save beatngu13/724a9a78bba61da96566ac5478c2d37b to your computer and use it in GitHub Desktop.
Easily handle Java system properties with JUnit 5 extensions
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
@Retention( RetentionPolicy.RUNTIME )
@Target( ElementType.METHOD )
@ExtendWith( SystemPropertyExtension.class )
public @interface SystemProperties {
SystemProperty[] value();
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
@Retention( RetentionPolicy.RUNTIME )
@Target( ElementType.METHOD )
@Repeatable( SystemProperties.class )
@ExtendWith( SystemPropertyExtension.class )
public @interface SystemProperty {
String key();
String value() default "";
}
import java.util.Properties;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
public class SystemPropertyExtension implements BeforeEachCallback, AfterEachCallback {
private static final String BACKUP_STORE_KEY = "backup";
@Override
public void beforeEach( final ExtensionContext context ) throws Exception {
final Properties backup = new Properties();
backup.putAll( System.getProperties() );
final Store store = context.getStore( Namespace.create( getClass(), context.getRequiredTestMethod() ) );
store.put( BACKUP_STORE_KEY, backup );
final Method testMethod = context.getTestMethod().get();
if ( testMethod.isAnnotationPresent( SystemProperty.class ) ) {
final SystemProperty prop = testMethod.getAnnotation( SystemProperty.class );
prepareSystemProperty( prop );
} else {
final SystemProperties props = testMethod.getAnnotation( SystemProperties.class );
Arrays.stream( props.value() ).forEach( this::prepareSystemProperty );
}
}
private void prepareSystemProperty( final SystemProperty prop ) {
if ( prop.value().isEmpty() ) {
System.clearProperty( prop.key() );
} else {
System.setProperty( prop.key(), prop.value() );
}
}
@Override
public void afterEach( final ExtensionContext context ) throws Exception {
final Store store = context.getStore( Namespace.create( getClass(), context.getRequiredTestMethod() ) );
final Properties backup = store.get( BACKUP_STORE_KEY, Properties.class );
System.setProperties( backup );
}
}
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
class SystemPropertyExtensionTest {
@BeforeAll
static void setUpOnce() {
System.setProperty( "some property", "old value" );
}
@SystemProperty( key = "some property" )
@Test
void extension_should_set_property_to_null() {
Assertions.assertNull( System.getProperty( "some property" ) );
}
@SystemProperty( key = "some property", value = "new value" )
@Test
void extension_should_set_property_to_value() {
Assertions.assertEquals( System.getProperty( "some property" ), "new value" );
}
@SystemProperty( key = "some property" )
@SystemProperty( key = "another property", value = "new value" )
@Test
void extension_should_be_repeatable() {
Assertions.assertNull( System.getProperty( "some property" ) );
Assertions.assertEquals( System.getProperty( "another property" ), "new value" );
}
@AfterAll
static void tearDownOnce() {
Assertions.assertEquals( System.getProperty( "some property" ), "old value" );
}
}
@beatngu13
Copy link
Author

beatngu13 commented Jul 11, 2019

For those who are interested: I have proposed this feature to be part of JUnit Pioneer (see junit-pioneer/junit-pioneer#129).

Now part of JUnit Pioneer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment