Saturday, July 29, 2017

JUnit Test for Singletons/Static Variables

JUnit runs all tests in one instance of JVM. Therefore, it assumes individual test cases are independent and should not interfere each other. However, this is not true for singletons or static variables. The status of singletons and static variables carry over across test cases. This causes troubles for JUnit tests.
Let me show you an example. Assume we have a MyService class: MyService class is a typical implementation of singleton. In addition, it has two methods:
init(String config)
to initialize MyService with a config parameter. This method can only call once.
doSomeService(FileWriter)
ask MyService to do something. In this example, it writes the value of someConfig via FileWriter parameter.
Now, we want to implement some JUnit test classes to verify the implementation. The first test class initializes MyService with "Hello!" and verifies whether doSomeService(...) really tries to write "Hello!". The second test class initializes MyService with "Hi!" and verifies whether doSomeService(...) really tries to write "Hi!". If you run the above test cases one-by-one in your IDE, it works fine. However, if you run both test cases in one go, one of the test cases fails:
As mentioned at the beginning, JUnit tests are run in one instance of JVM. If you run both test cases, because of singleton design pattern, the MyService instance of first test case is carried over to the second test case. When the second test case calls the init(...) method, it throws exception. This is actually one of the infamous disadvantages of singleton design pattern. However, you may not be able to re-design your system. Then, how can we fix the unit tests?

Actually, there is a workaround to force reloading of classes for each test using class loader trick. For each JUnit test class, we use a customized test runner which enforce a separated instance of class loader for each test class. Then, the classes we want to test will be reloaded for each JUnit test class Here is the implementation of the test runner (SeparateClassloaderTestRunner):
To use the SeparateClassloaderTestRunner, you need to replace the "@RunWith(MockitoJUnitRunner.class)" to "@RunWith(SeparateClassloaderTestRunner.class)" in the test classes. Then, if you run both test cases in one go, both test cases will pass.
You can get the demo source code at github - https://github.com/loklam/reloadclassdemo.

Thursday, July 27, 2017

Working Copy - a good Git Client for iPad

Recently, I want to read some source code located in GitHub. I found there is a handy tool - Working Copy. It's a Git Client for iPad. It has a nice code browser and code viewer/editor with syntax highlight. You can even edit the code and commit the changes. Now, I can read code during travelling.