Mocking singleton with PowerMockito - java

in order to test one of the private method I coded, I need to mock a Singleton.
After testing several methods with PowerMockito :
PowerMockito.mockStatic(UtilDatabaseSoldeAutoCdeCommon.class);
Mockito.when(UtilDatabaseSoldeAutoCdeCommon.getInstance()).thenReturn(mockDatabase);
I could never mock this class. Thus I cannot test my methods as in every of them, I access to database.
UtilDatabaseSoldeAutoCdeCommon is defined as such :
public class UtilDatabaseSoldeAutoCdeCommon extends AbstractUtilDatabase {
private static UtilDatabaseSoldeAutoCdeCommon instance;
private UtilDatabaseSoldeAutoCdeCommon() {
super();
}
public static UtilDatabaseSoldeAutoCdeCommon getInstance() {
if(instance == null) {
instance = new UtilDatabaseSoldeAutoCdeCommon();
}
return instance;
}
...
}
I debugged powermockito when it calls getInstance() but everytime consructor is called, it crashes as it tries to load configuration file (which does not exist).
I precise that config file is defined as a constant in absract parent class of UtilDatabaseEnrichissement and used in constructor.
How could I test this part ?

I think this should work:
#PrepareForTest({UtilDatabaseSoldeAutoCdeCommon.class})
public class SomeTest {
#Mock
UtilDatabaseSoldeAutoCdeCommon fakeSingletonInstance;
#Test
public void test() {
Whitebox.setInternalState(UtilDatabaseSoldeAutoCdeCommon.class, "instance", fakeSingletonInstance);
// Write here your test
}
}

This question was asked long time back and I was facing similar issue and unable to find good answers hence answering it now. I tested the class with suppressing constructor like
PowerMockito.suppress(UtilDatabaseSoldeAutoCdeCommon.class.getConstructors());

PrepareForTest the singleton class you mock

Related

MockitoException when trying to mock java.lang.System

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

how to prevent invoke private constructor through reflect in Java

I have a java class named Test which has a single, private constructor because I require it to be a singleton, like this:
class Test {
private static final Test INSTANCE = new Test();
private Test() { }
public static Test getInstance() { return INSTANCE; }
// other code
}
How to prevent others from instantiating Test through reflection in Java?
You can throw exception in private contructor if object is already created,
private Test() {
if (INSTANCE != null)
throw new IllegalArgumentException("Instance already created");
}
You can use enum as they are internally created, initialized by JVM. Invocation of enum is also done internally, so they cannot be accessed by reflection as well
public enum Test
{
INSTANCE;
//other methods etc
}
PS: drawback is you won't be able to lazy initialize it. However some threads have suggested that they can be lazy intialized
https://stackoverflow.com/a/15470565/4148175 , https://stackoverflow.com/a/16771449/4148175

Mocking getInstance of a singleton using PowerMock

I have the following Singleton that returns an instance of a different class. I want to mock the method on that returned instance object. I've been reading on PowerMock mocking features for final classes and singletons but I don't know if my case falls under those or not. I appreciate some suggestion.
public final class SomeWrapper {
private MyActualObject MyActualObject;
private static final SomeWrapper instance = new SomeWrapper();
private SomeWrapper() {
// singleton
}
public static SomeWrapper getInstance() {
return instance;
}
public void setMyActualObject(MyActualObject MyActualObject) {
if(this.MyActualObject == null) {
this.MyActualObject = MyActualObject;
} else {
throw new UnsupportedOperationException("MyActualObject is already set, cannot reset.");
}
}
public MyActualObject getMyActualObject() {
return MyActualObject;
}
}
So now in my unit test, I wanna mock the following line:
when(SomeWrapper.getInstance().getMyActualObject().isActive()).thenReturn(false);
Should I mock the SomeWrapper and MyActualObject? Any code sample as guidance?
Using these Mockito & PowerMock versions:
testImplementation 'org.mockito:mockito-core:2.23.4'
testImplementation 'org.powermock:powermock-module-junit4:2.0.0-beta.5'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.0-beta.5'
You are able to mock an android MainApplication singleton instance (for example) using PowerMock.mockStatic() and the when() mechanism, like this:
private MainApplication mApplication;
#NonNull
protected MainApplication getApplication() {
if (mApplication == null) {
mApplication = PowerMockito.mock(MainApplication.class);
PowerMockito.mockStatic(MainApplication.class);
PowerMockito.when(MainApplication.getInstance()).thenReturn(mApplication);
PowerMockito.when(mApplication.getBaseContext()).thenReturn(mApplication);
PowerMockito.when(mApplication.getApplicationContext()).thenReturn(mApplication);
}
return mApplication;
}
Mocking the private constructor could be tricky - you might try the approach suggested in this post, by using a substitute class in the thenReturn() call:
SO - Mocking Private Constructor
The point here is: you wrote hard-to-test code. And yes, PowerMock can help "fixing" that, but you might prefer to simply rework your production code to make it easier to test.
For example, by adding a package protected constructor like:
SomeWrapper(MyActualObject myActualObject) {
this.MyActualObject = myActualObject;
}
This would allow you to create an instance of SomeWrapper class that receives a completely valid MyActualObject instance.
In that sense: you might want to learn how to create production code that is actually testable.

Running JUnit tests with different data

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.

Issue mocking a class variable value in java

I have a class that has a private class variable initialized like
public class MyClass{
private BusinessObject businessObject = BusinessObjectGenerator.getBusinessObject();
public MyClass(){
}
public Object myMethodToTest(){
return businessObject.getObject();
}
}
Now, I'm trying to unit test myMethodToTest I want to send in a mock object in place of businessObject. I use mockito for mocking and use spy(new MyClass()) for partial mocking but having trouble with mocking the call to get businessObject.
1. Is it possible to mock the call to the businessObject? If so how?
2. How can I refactor this code to help while writing unit test. Any resources pointing towards this would be of great help.
Thanks!
To properly refactor this code you'd:
private BusinessObject businessObject;
public void setBusinessObject(BusinessObject instance) {
businessObject = instance;
}
private BusinessObject getBusinessObject() {
if (businessObject == null) {
// represents existing implementation in original code sample
businessObject = BusinessObjectGenerator.getBusinessObject();
}
return businessObject;
}
/* rest of your code */
Now you can inject your mock into the class yourself at the test site.
I'd recommend doing this using dependency injection with a framework like Guice. It will be worth your time.

Categories