What is the recommended pattern to modify constants for unit tests? This is currently what I've used for some time and today I realized it's flawed.
Assume my class looks like this
class Foo {
private static final int MAX_TIME = Integer.getInteger("myProp", 1000);
...
}
The fact that I use a VM property is not only to modify it in a unit test. It is because I want it to be immutable from the actual code and I don't want to pollute a constructor with it since it is an implementation detail.
So, in production I want a timeout of 1 second; however that's too long for unit tests so I do this
class FooTest {
#Before
public void setUp() {
System.setProperty("myProp", "50");
}
#Test
public void testThatAssumesTimeoutOf50() { ... }
}
This worked fine for a long time until today I finally added a BarTest like this
class BarTest {
Foo mockFoo = mock(Foo.class); //actually done in a #Before method in the real code
}
Now what this created is that my tests fail or pass depending on the order of execution. If Foo is tested first, the test that assumes a testing timeout of 50ms passes. But if Bar is tested first then this makes Foo to be loaded due to the mock so MAX_TIME takes the default value of 1000 and then when BarTest ends and FooTest starts, the test that assumes a testing timeout of 50ms now fails.
The easiest way is probably to remove the final keyword. This will let you change the value after class loadtime.
Since you set and get the value across many different classes, and possibly packages, you should probably add a getter and setter. If you need to change this value across packages, then it will have to be public.
class Foo{
public static int getMaxTime(){
return MAX_TIME;
}
public static void changeMaxTime(int timeout){
//validation logic goes here
this.MAX_TIME = timeout;
}
Then, in your test classes, you should save the old value in the #BeforeClass or #Before phase, change it to whatever you want, and then restore the old value in the #AfterClass or #After phase.
Since it looks like you do this across many test classes, it might be best to actually make your own Test Rule:
public class TimeoutRule extends ExternalResource {
private final int oldTimeout, newTimeout;
public TimeoutRule(int timeout){
this.oldTimeout = Foo.getMaxTime();
this.newTimeout = timeout;
}
#Override
protected void before() {
}
#Override
protected void after() {
//restore old timeout
Foo.setMaxTimeOut(oldTimeout);
}
}
Then in your test code:
class FooTest {
#Rule
public TimeoutRule timeoutRule = new TimeoutRule(50);
#Test
public void testThatAssumesTimeoutOf50() { ... }
}
That code will reset the timeout to 50 ms and then restore it to the original value after every test. If you wanted to only do it once per test class, use #ClassRule instead (and make the field static)
Related
I have a test case that mock a static method of java.lang.System class:
#Test
fun `getLocalTime()`() {
// Arrange
val staticMock = Mockito.mockStatic(System::class.java)
Mockito.`when`(System.currentTimeMillis()).thenReturn(1000L)
// Action
val res = deviceTimeProvider.getLocalTime()
// Assert
Truth.assertThat(res).isEqualTo(1000L)
staticMock.close()
}
But when I run the test, I got this error:
org.mockito.exceptions.base.MockitoException: It is not possible to
mock static methods of java.lang.System to avoid interfering with
class loading what leads to infinite loops
Why does this happen? How can I mock methods of java.lang.System class?
While Mockito since 3.4.0 version allows mocking static methods it is not allowed to mock the Thread and System static methods, see this comment on github
Finally note that Mockito forbids mocking the static methods of System (and Thread). Those methods are to much cemented into class loading which happens in the same thread. At some point, we might add instrumentation to class loading to temporarily disable the static mocks within it to make mocking these classes, too, where we also would need to disable their intensification properties. You can however easily mock Instant.now().
If you like ugly solutions you can still mock System with PowerMockito
#PrepareForTest(System.class)
public class TestCase {
#BeforeClass
public void setup() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.currentTimeMillis()).thenReturn(1000L);
}
...
But I would avoid mocking System classes if possible. You can still wrap it in method and mock this method.
To mock the static methods of java.lang.System class with the help of Mockito.
Create an interface i.e ISystem.java
public interface ISystem {
String getProperty(String name);
Long getCurrentTimeInMillis();
}
2- Create the implementation class of ISystem interface i.e ISystemImpl.java
public class ISystemImpl implements ISystem {
#Override
public String getProperty(final String name) {
return System.getProperty(name);
}
#Override
public Long getCurrentTimeInMillis() {
return System.currentTimeMillis();
}
}
3- Use Isystem.java inside your DeviceTimeProvider.java class.
public class DeviceTimeProvider {
#NonNull private final ISystem mISystem;
public DeviceTimeProvider(ISystem iSystem){
mIsystem = iSystem;
}
public Long getLocalTime(){
return mIsystem.getCurrentTimeInMillis()
}
}
4- Now finally mock the ISystem interface inside your test class.
public class DeviceTimeProviderTest {
private ISystem mISystem;
private DeviceTimeProvider sut;
#Before
public setup(){
mIsystem = mockito.mock(ISystem.class)
sut = new DeviceTimeProvider(mISystem);
}
#Test
public void getDeviceLocalTime(){
Long expectedTime = 1000L;
mockit.when(mISystem.getCurrentTimeInMillis()).thenReturn(expectedTime);
Long actualTime = sut.getLocalTime();
Assert.assertEquals(actualTime, expectedTime);
}
}
OUTPUT
I have just started learning JUnit very recently and came across the following problem.
Have a look at the following class
class MyClass {
String a;
public MyClass(String a) {
this.a=a;
String doSomething(String a) {
if( a.isEmpty() )
return "isEmpty";
else
return"isNotEmpty";
}
I want to test the above method for both the conditions. If I proceed with the general structure of writing testcases it will look something like this:
class MyClassTest {
MyClass myClass;
#BeforeEach
void setUp() {
myClass=new MyClass("sampleString");
}
#Test
void doSomethingTest() {
Assertions.equal("isNotEmpty", myClass.doSomething());
}
}
However, for testing the empty string condition I will need another setup method where instead of "sampleString" I pass an empty string.
Following are the approaches I could think of and the questions for each:
Not use setUp at all and instead initialize the class in the individual test method. However, if let's say there are 10 testcases; 5 of which require empty string and rest "sampleString" then this doesn't make sense. Again, we can have a separate method for this repetitive code and call it individually in each testcase but then that defeats the purpose of having a steup method. Lets say I wanted to use two different setup methods, is there a way to do so?
Have a parameterized setup. I don't know if this is possible though. If yes, please share some useful links for this.
Use TestFactory. I tried reading up about this, but couldn't find an example for this specific case. If you have any, please share.
This example has been kept simple for illustrative purposes.
Group the tests with the same setup in an inner class annotated with #Nested. Each nested test class can have its own setup in a local #BeforeEach method.
You can always prepare the non-common data inside your test method. I've always thought it's easier this way, compared to using parameterized tests. You can't mix parameterized and non-parameterized tests in 1 file.
#Test
void doSomething_nullString()
{
myClass = new MyClass(null);
Assert.assertNull(myClass.doSomething());
}
#Test
void doSomething_emptyString()
{
myClass = new MyClass("");
Assert.assertEquals("", myClass.doSomething());
}
#Test
void doSomething_nonEmptyString()
{
myClass = new MyClass("sampleString");
Assert.assertEquals("sampleString", myClass.doSomething());
}
Or, you can always have helper methods inside the test class.
private MyClass createTestObject_nonNullString() {
return new MyClass("nonNullString");
}
private MyClass createTestObject_nullString() {
return new MyClass(null);
}
#Test
public void doSomething_sample() {
MyClass test = createTestObject_nonNullString();
// perform test
}
Is it possible to control the value of the global variable in the class that I test?
The global variable is used in a private method, so I use a public method (in the same class) to pass through it.
How can I say that mListValService != null?
public class Myclass {
//my global variable
private ListValServiceRemote listValService = null;
public String getCodeValeurRef(Long idValeur) {
return getListValService().getRlvCode(idValeur);
// I want 100% coverage on this method so i have to change the value
// of mListValService.
private ListValServiceRemote getListValService() {
if (listValService == null) {
listValService = ServiceGetter.getListValService();
}
return listValService;
}
ReflectionTestUtils from spring-test might be a solution to access the field value. You can also use plain old reflection, add getter/setter to the field or make the field protected and put the test in the same package as the tested class.
Sample test:
public class MyclassTest {
private MyClass myClass;
#Before
public void setup() {
this.myClass = new MyClass();
}
#Test
public void testGetListValServiceWhenFieldIsNull() {
assertNotNull(this.myClass.getListValService());
}
#Test
public void testGetListValServiceWhenFieldIsNotNull() {
final ListValServiceRemote lvsr = new ListValServiceRemote();
ReflectionTestUtils.setField(this.myClass, "listValService", lvsr);
assertSame(lvsr, this.myClass.getListValService());
}
}
First of all, seems you are not using IoC technique, and hence you have problems while unit testing the code.
Secondly, a private is the private, don't test it. Your code should be tested and covered only by using public methods. If some code is not reachable via public interface, then it is not reachable at all. Why do you want to test it then?
This particular code could be easily 100% covered if you just invoke getCodeValeurRef() twice. And also if you would have listValService == null, it will cause NullPointerException failing the test anyway, so an assert is not required.
You could expose the getListValService() method as package-private, then call it in a test. You can confirm the same value is returned each time:
#Test
public void sameListValTest() {
Myclass foo = // construct this somewhow
assertTrue(foo.getListValService() == foo.getListValService());
}
This will give you 100% coverage without fiddling with a private field.
Or you could just call getCodeValeurRef() twice in your test to achieve the same results. Anything that causes the getListValService() to execute twice will give you 100% coverage. Exposing it as package-private allows you to verify that you are re-using the same field, not creating one each time (if that's important).
I want to know if there is any technical difference between the following, when writing JUnit tests:
Option 1:
Define a setup method, i.e annotated with #Before, to initialize test fixture state before any #Test method is run.
Option 2:
Define a private method - just a plain old private method without any annotation - that does the same initialization, and make the first line of every #Test method a call to this method. (Ignore the possibility of someone forgetting to call the method in every test. I am looking for technical differences, not human factors)
Example of Option 2:
public class MyTest {
private void runSetupLogic() {
// whatever #Before method would have done
}
#Test
public void testMethod1() {
runSetupLogic();
// test logic
}
#Test
public void testMethod2() {
runSetupLogic();
// test logic
}
}
They are not really exactly the same, but for all intents and purposes either way should be fine. However, if you are interested in the technical analysis then my shaky understanding of the current JUnit 4 code on Github follows:
Here is what seems to be the actual code being ran when you use #Before using the default JUnit 4 runner src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java:
/**
* Returns a {#link Statement}: run all non-overridden {#code #Before}
* methods on this class and superclasses before running {#code next}; if
* any throws an Exception, stop execution and pass the exception on.
*/
protected Statement withBefores(FrameworkMethod method, Object target,
Statement statement) {
List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
Before.class);
return befores.isEmpty() ? statement : new RunBefores(statement,
befores, target);
}
The above calls RunBefores in src/main/java/org/junit/internal/runners/statements/RunBefores.java:
public class RunBefores extends Statement {
private final Statement next;
private final Object target;
private final List<FrameworkMethod> befores;
public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
this.next = next;
this.befores = befores;
this.target = target;
}
#Override
public void evaluate() throws Throwable {
for (FrameworkMethod before : befores) {
before.invokeExplosively(target);
}
next.evaluate();
}
The invokeExplosively method definition is in src/main/java/org/junit/runners/model/FrameworkMethod.java:
public Object invokeExplosively(final Object target, final Object... params)
throws Throwable {
return new ReflectiveCallable() {
#Override
protected Object runReflectiveCall() throws Throwable {
return method.invoke(target, params);
}
}.run();
}
which seems to use reflection to invoke the methods annotated with #Before.
Anyway, hope this answer is somewhat correct, but I'm not sure. If anyone has any corrections I can edit them in from the comments. By the way, for reference here is the javadoc for the #Before annotation: http://junit.org/javadoc/latest/org/junit/Before.html
I do not believe so.
However, if you were you implement another function, such as tearDown(), that would function essentially as an #After method, I would argue you might as well use them for readability, for the benefit of other collaborators or maybe even yourself.
The upside to using #Before and #After annotations is the that they avoid having to call a method at the beginning of each unit test, designed to save you the extra maintenance. If for some reason you had forgotten to add the call to your setUp() and/or tearDown() method, who knows what could go wrong.
This is, of course, if you need the EXACT SAME setup before each test. If you envision having a completely different setup for different unit tests, than perhaps you should look at the functionality of the class you are testing and ask yourself if perhaps you could modularize more.
The benifit comes from reporting.
In your method: runSetupLogic()
when ran from the start of a test, is reported within the test. Not as part of the setup and not as part of the initialization.
If the setup method fails, you get an accurate description of what failed... setup vs testing.
The before method allows you to isolate test failures from setup failures and allows the reporting solution to know as well.
I have a suite of unit tests. I have a static variable which gets initialized in setup() method. I want to run all my suite of unit tests with two different values of that static variable.
Static variable in setup() gets initialized to an object which is a singleton. So, I can't(I think I can't) use JUnit parametrized tests.
I have to run all the tests with one value of that static variable, and then run all the tests with other value of static variable.
Any ideas on how to do this in an elegant way if possible.
Code below if my description above is not very easy to understand
public class MyClassTest{
private static final Dep_class dep_obj;
public static void setup(){
dep_obj = Dep_class.getInstance("VALUE_1");
//You can have only instance of Dep_class at any time.
//So for second run I need to do a
//dep_obj = Dep_class.getInstance("VALUE_2") and run my tests.
}
public void test_mymethod(){
//do something with dep_obj
}
Try this
#RunWith(Parameterized.class)
public class MyClassTest {
private Object dep_obj;
public MyClassTest(String val) {
dep_obj = val;
}
#Parameters
public static Collection<?> data() {
Object[][] data = { { "val1" }, { "val2" }, { "val3" } };
return Arrays.asList(data);
}
#Test
public void test() {
System.out.println(dep_obj);
}
}
So first of all, I would question why you have a singleton that is initialized in this way. It seems as if adding an argument to your .getInstance(String s) method would add ambiguity and unexpected behavior, as this String argument will just be disregarded after instantiation (unless you're re-instantiating it if the type changes, in which case it will be highly unpredictable at runtime).
In any case, an easy way to do this would be to abstract the test_mymethod() to a parent class and have two child test classes that each instantiate a different instance of the singleton. Since your JVM will not restart, you'll also need something like PowerMock to reset the singleton to a pre-loaded state before running any tests.
So the parent class would look like so (JUnit annotations added):
public abstract class MyAbstractTestClass {
private final Dep_class dep_obj;
#Before
public abstract void setup(){
// Begin by ensuring that the singleton instance is initialized to null -
// this is highly important, since subclasses will not be able to rely on
// an un-initialized state
Whitebox.setInternalState(dep_obj.getInstance(/*default, arbitrary, or null value*/, "instance", null);
// Now leave the actual singleton initialization to child classes
dep_obj = getSingleton();
}
public abstract Dep_class getSingleton();
#Test
public void test_mymethod(){
//do something with dep_obj
}
}
I made a few assumptions with Powermock - namely that your singleton properly checks to see if the instance is null and if so, initializes it. In this case, I'm assuming that the variable name for your instance is "instance". Next, your child classes would look like this:
public class MyTestClass1 extends MyAbstractTestClass {
#Override
public void Dep_class getSingleton() {
return Dep_class.getInstance("VALUE_1");
}
}
public class MyTestClass2 extends MyAbstractTestClass {
#Override
public void Dep_class getSingleton() {
return Dep_class.getInstance("VALUE_2");
}
}
Again, I would strongly encourage you to re-think implementing a singleton in this way. Singletons should be rarely used anyway - an implementation like this on top of a questionable design pattern is an eyebrow raiser. This question goes over some good guidelines for usage - make sure that your singleton fits this criteria.