Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Re-loading static variables at the start of every unit test

I'm unit testing an SDK with lots of static methods. And I don't want the operations I do in test1() to have an effect on the operations I do in test2(). At the start of every test, I need all the static variables within the SDK to go back to uninitialized state as if they weren't loaded. And then load them again. Any suggestions on how to do that? Is there any provision for something like that in Robolectric? Because I use that for unit testing. In plan English, what I basically want is a clean slate at the start of every test.

@Test
public void test1() throws Exception {
    // Setup all the device info values
    MyDeviceInfoClass.setDeviceModel().equals("Nexus 4");
    MyDeviceInfoClass.setDeviceOperatingSystem().equals("Android_3.4b5");

    // Verify all the device info values set previously
    assertTrue(MyDeviceInfoClass.getDeviceModel().equals("Nexus 4"));
    assertTrue(MyDeviceInfoClass.getDeviceOperatingSystem().equals("Android_3.4b5"));
}

That was the first test and it succeeds. Just the way it should be. Then in the second test:

@Test
public void test2() throws Exception {
      // Setup all the device info values
      MyDeviceInfoClass.setDeviceOperatingSystem().equals("Android_4.2");

      //The following line also succeeds if test1() is finished. But I do not want that. This line should throw an assertion error because we did not specify what the device is over here in test2().
      assertTrue(MyDeviceInfoClass.getDeviceModel().equals("Nexus 4"));
      //This will succeed just the way it should be.
      assertTrue(MyDeviceInfoClass.getDeviceOperatingSystem().equals("Android_4.2"));
}

I do not want the values set in the first test to have an effect on values being fetched in the second test. The test shown above are simple examples. But the SDK that I am unit-testing is more complicated than that.

To put it more clearly, I don't want the values being set in test1() to have any effect on the operations being done in test2(). If I set device model to Nexus 4 in test1() like this MyDeviceInfoClass.setDeviceModel().equals("Nexus 4"), the second test test2() doesn't have to know about it when I fetch it via MyDeviceInfoClass.setDeviceModel().equals("Nexus 4"). I want complete isolation between my unit-tests.

Also going away from static methods is not an option. Please tell me how I can achieve this.

EDIT: Resetting all the static variables before the start of a test is not an option either because of certain complexities involved in the project.

like image 910
iamronak Avatar asked Oct 22 '22 06:10

iamronak


1 Answers

The only time static variables are unloaded is when the classloader that loaded the class in question is garbage collected.

One way to solve your problem is to use your own classloader. There's a great SO question here that covers this in fairly extensive detail.

Another option would be simply resetting the values prior to each test. You can supply a @Before annotated method in your test class that would reset them, using reflection if necessary.

like image 197
Brian Roach Avatar answered Oct 23 '22 21:10

Brian Roach