Search code examples
javajunit4powermockeasymock

Is there a way to test that default TimeZone is never used in a JUnit Test using EasyMock/PowerMock?


I'd like to prove that a piece of code that I've written is not affected by the default Timezone (set either as a JVM property or through the setDefault() method) as part of a unit test.

Is there a way to accomplish this?


The reason that this isn't as simple as setting default Timezone within the test before calling the method is that I'm trying to test safety against a race condition. For example, consider the following:

Calendar calendar = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();

assertEquals(calendar.get(Calendar.DATE), calendar2.get(Calendar.DATE));

This test should pass, but what happens if the default timezone suddenly changes between the two getInstance() calls, from GMT to Singapore, because another piece of code running somewhere changes the default timezone? Then we have a situation where it might fail.

The only way that I can think of to show that it will be unaffected for all possible changes is to somehow assert that the code does not access the default timezone value, wherever it is.


Solution

  • In this case, I would provoke the race condition. You add an artificial method to your code and use a partial mock or an manual mock to change the timezone.

    Calendar calendar = Calendar.getInstance();
    changeTimeZone();
    Calendar calendar2 = Calendar.getInstance();
    
    assertEquals(calendar.get(Calendar.DATE), calendar2.get(Calendar.DATE));
    

    If the idea is just to know if a setDefault is called somewhere during your code execution, you can use PowerMock to mock setDefault and fail if it is called. However, I'm not sure PowerMock can mock java.* classes. You might need a ByteBuddy agent.

    There is one pitfall left. The default locale can be set using system properties. However, if the property is changed between the two getInstance(), it won't matter.