in eclipse/Junit with multiple tests how to retrieve initial default directory

When I use junit to execute one test, I can find files in current directories, i.e. start directory, or change it relatively, by setting user.dir.

But when I launch multiple tests, user.dir remains between tests, then it is a mess, if I set it before.

How can each test get the initial default directory, even if it was changed by a previous test, without to set each configuration of test (-Duser.dir ...)

Thanks to GhostCat, here is one short solution:

static String user_dir_initial="";  
@Before
       public void before()
        {
    if (user_dir_initial.contentEquals(""))
        user_dir_initial=System.getProperty("user.dir");
        System.out.println("USER DIR INITIAL:"+user_dir_initial);
        System.setProperty("user.dir", user_dir_initial);
        }

Upvotes: 2

Views: 333

Answers (2)

glytching
glytching

Reputation: 47875

If you set user.dir as a system property then, unless you remove it, it will be present for the lifetime of that JVM. So, you must either spawn a new JVM for each test or somehow manage that system property between test cases. You can use a JUnit Rule to set/unset a system property quite easily.

Here's an example:

public class SystemPropertyRule extends ExternalResource {
    private final Map<String, String> properties = new LinkedHashMap<String, String>();
    private final Map<String, String> restoreProperties = new LinkedHashMap<String, String>();

    public SystemPropertyRule(String propertyName, String propertyValue) {
        this.properties.put(propertyName, propertyValue);
    }

    @Override
    protected void before() throws Throwable {
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            String propertyName = entry.getKey();
            String propertyValue = entry.getValue();
            String existingValue = System.getProperty(propertyName);
            if (existingValue != null) {
                // store the overriden value so that it can be reinstated when the test completes
                restoreProperties.put(propertyName, existingValue);
            }
            System.setProperty(propertyName, propertyValue);
        }
    }


    @Override
    protected void after() {
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            String propertyName = entry.getKey();
            String propertyValue = entry.getValue();
            if (restoreProperties.containsKey(propertyName)) {
                // reinstate the overridden value
                System.setProperty(propertyName, propertyValue);
            } else {
                // remove the (previously unset) property
                System.clearProperty(propertyName);
            }
        }
    }
}

You would use this in your tests cases like so:

@ClassRule
public static final SystemPropertyRule systemPropertyRule = new SystemPropertyRule("foo", "bar");

@Test
public void testPropertyIsSet() {
    Assert.assertEquals("bar", System.getProperty("foo"));
}

This rule will wrap test case invocations adding the following behaviour:

  • Before: Set a named system property with the given value
  • After: Either discard the property (if it was not set before this test case was run) or reinstate the previous value for this property (if this property had a value before the test case was run)

With this rule, you can control setting user.dir for each of your tests (allowing for it to be set/unset/reinstated etc) and although it does ultimately amount to invoking user.dir=... for each test it is not very intrusive and it uses a JUnit mechanism which is intended for this very purpose.

Upvotes: 1

GhostCat
GhostCat

Reputation: 140427

If you want to make sure that a certain property is set for all test cases, you can use the @Before or @BeforeClass annotation in conjunction with System.setProperty() to force a certain setting.

If you have to undo, you can use @After or @AfterClass in a symmetric way!

Upvotes: 1

Related Questions