I have a dependency on an enum singleton class like
public enum SingletonObject {
INSTANCE;
SingletonObject() {
// some annoying initialization
}
public callDB() {
this.num = num;
}
}
I am trying to test a class like
public class MyClass {
public void doSomething() {
// some code
SingletonObject.INSTANCE.callDB();
}
}
Following this answer, I've tried simply testing the mock with the following code, but I seem to be running into problems with the enum calling its constructor
public class MyClassTest {
#Mocked
private SingletonObject singleton;
#Before
public void setup() {
Deencapsulation.setField(SingletonObject.class, "INSTANCE", singleton);
}
#Test
public void test() {
assertSame(singleton, SingletonObject.INSTANCE);
}
}
Using an interface seems somewhat promising, but I question whether that is the best way of going about this problem.
It looks like PowerMockito is promising as well, but I would like to save that as a last resort for various reasons.
So how can I mock this enum singleton without invoking its constructor?
Try something like this. This creates a partial-mock of 'MyClass' and a Mock SingletonObject, calls the (real) doSomething method of MyClass, and confirms that the (mock) callDB() method of SingletonObject is invoked by it precisely once.
#Test
public void testdoSomething(
#Mocked final SingletonObject singleton)
{
final MyClass clz = new MyClass();
new Expectations(clz)
{
{
SingletonObject.INSTANCE.callDB();
times = 1;
}
};
clz.doSomething();
}
Related
What is the right / most popular way to utilize the Singleton Pattern.
Limit the no. of calls to getInstance(), preferably call it only once, and pass the object around to other classes during their instantiation?
class SingletonClass {
// Implementataion
}
class MainClass {
private SingletonClass singletonClassObject;
public MainClass() {
singletonClassObject = SingletonClass.getInstance();
new SomeClass(singletonClassObject).doSomething();
new SomeOtherClass(singletonClassObject).doSomethingElse();
}
}
class SomeClass {
private SingletonClass singletonClassObject;
public SomeClass(SingletonClass singletonClassObject) {
this.singletonClassObject = singletonClassObject;
}
public void doSomething() {
System.out.println(singletonClassObject.getStuff());
}
}
class SomeOtherClass {
private SingletonClass singletonClassObject;
public SomeOtherClass(SingletonClass singletonClassObject) {
this.singletonClassObject = singletonClassObject;
}
public void doSomethingElse() {
System.out.println(singletonClassObject.getStuff());
}
}
Don't pass the singleton object around. Rather call get the object reference in each class and save the reference as an instance variable and use it wherever required.
class SingletonClass {
// Implementataion
}
class MainClass {
public MainClass() {
new SomeClass().doSomething();
new SomeOtherClass().doSomethingElse();
}
}
class SomeClass {
private SingletonClass singletonClassObject;
public SomeClass() {
singletonClassObject = SingletonClass.getInstance();
}
public void doSomething() {
System.out.println(singletonClassObject.getStuff());
}
}
class SomeOtherClass {
private SingletonClass singletonClassObject;
public SomeOtherClass() {
singletonClassObject = SingletonClass.getInstance();
}
public void doSomethingElse() {
System.out.println(singletonClassObject.getStuff());
}
}
Don't even save the reference as an instance variable, rather use SingletonClass.getInstance() everywhere you need the object.
class SingletonClass {
// Implementataion
}
class MainClass {
public MainClass() {
new SomeClass().doSomething();
new SomeOtherClass().doSomethingElse();
}
}
class SomeClass {
public SomeClass() {
}
public void doSomething() {
System.out.println(SingletonClass.getInstance().getStuff());
}
}
class SomeOtherClass {
public SomeOtherClass() {
}
public void doSomethingElse() {
System.out.println(SingletonClass.getInstance().getStuff());
}
}
How do these approaches compare with each other w.r.t. better design, testability etc? Which is better and why?
If we assume for a moment that SingletonClass is not a singleton and we do not get an instance by calling static method we face another problem, how to link these classes together. This problem is solved by Dependency Injection and this concept is well described here:
Inversion of Control Containers and the Dependency Injection pattern
Unit Testing 101: Inversion Of Control
After reading above it should be easy to choose option .1 where all classes get in constructor references to required dependencies. You can even create an interface for a behaviour you need and implement it in SingletonClass. Now you see, that a fact that class implements Singleton pattern does not make it special and we should inject them like other classes. All benefits from using DI you can apply to your class.
Just compare it with .3 and you need to write a test where you need mock something. It would be more unpleasant task then in case of .1.
Look at it this way: you're questioning the compiler's ability to recognize that a static final reference can be compiled as an inline reference.
I would guess the compiler converts the getInstance() to an inline reference. I would be less confident that the compiler would recognize that you're intentionally creating extra work for yourself when you pass a reference by value, and that it would create an extra reference on the stack when you passed it around.
My guess is that getInstance() would be more efficient.
Am trying to mock one static void method, I tried PowerMock but always getting NullPointer exception.
We are trying to mock the below call -
public Class XYZ{
public void method1(){
....
SampleClass.methodTypeStatic1().methodTypeStatic2("xyz", "mno", classVeriable);
}
And the main class is -
public class SampleClass implements SampleClassParent{
private static SampleClass var1;
public static SampleClass methodTypeStatic1(){
if (var1 == null) {
//Do something on var1
}
return var1;
}
public void methodTypeStatic2(String localVar1, String localVar2, DifferentStaticClass localVar3) {
//Do something
}}
Am trying to mock the call like this way in my test class -
#RunWith(PowerMockRunner.class)
#PrepareForTest({SampleClass.class})
public class XYZTest{
#InjectMocks
XYZ xyzTestService;
#Test
public void testMethod1(){
...
PowerMockito.mockStatic(SampleClass.class);
PowerMockito.doNothing().when(SampleClass.methodTypeStatic1());
xyzTestService.method1();
}
Also to be mentioned SampleClass.class is not a part of our code, we have imported this external class into our code base to perform some task.
If you want to mock a non-void method, you need to define the behaviour for this method on the mock. You get the doNothing for free (as this is what mocking does),
however you need to define what the method is supposed to return.
Your test could look like this:
#Test
public void testMethod1() {
SampleClass sample = new SampleClass();
PowerMockito.mockStatic(SampleClass.class);
PowerMockito.when(SampleClass.methodTypeStatic1()).thenReturn(sample);
XYZ xyzTestService = new XYZ();
xyzTestService.method1();
}
You didn't not mention any #Mock annotations, so using #InjectMocks does nothing for you besides creating the XYZ object.
I have MyClass and I am doing a test-class for every method (Method1Test)
public class MyClass {
public int method1(){
int a = method2();
return a;
}
public int method2(){
return 0;
}
}
#RunWith(MockitoJUnitRunner.class)
public class Method1Test {
#InjectMocks
private MyClass myClass = new MyClass();
#Before
public void setup(){}
#Test
public void test01(){
Mockito.when(myClass.method2()).thenReturn(25);
int a = myClass.method1();
assertTrue("We did it!!!",a==25);
}
}
The problem is that I am not able to mock the call to method2 to make it return a diferent value. The Mockito sentence don't do the work.
Very thanks ^_^
You have to create a spy on the class-under-test and partially mock it by redefining the behavior for the method2() of the spy
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
public class Method1Test {
private MyClass myClass = new MyClass();
#Test
public void test01(){
//given
MyClass spy = spy(myClass); //create a spy for class-under-test
when(spy.method2()).thenReturn(25); //partially override behavior of the spy
//when
int a = spy.method1(); //make the call to method1 of the _spy_!
//then
assertEquals(25, a);
}
}
Apart from this, you don't require neither the Mockito Runner nor the #InjectMocks for your test as you're doing no injection of #Mock annotated mocks into the class-under-test.
Further, the message in the assertTrue statement is only displayed, when the condition of the assertion is NOT fulfilled. So it should be at least "We failed!!!" ;)
In the end I find a transversal solution without create a new class (I haven't been able to do it because it is forbbiden in the actual project). I have overwrited the method in the test.
The solution is
public class MyClass {
public int method1(){
int a=0;
a=method2();
return a;
}
public int method2(){
return 1;
}
}
#RunWith(MockitoJUnitRunner.class)
public class Method1Test {
#InjectMocks
private MyClass myClass = new MyClass(){
public int method2(){
return 25;
}
};
#Before
public void setup(){}
#Test
public void test001(){
Mockito.when(myClass.method2()).thenReturn(25);
int a = myClass.method1();
assertTrue("We did it!!!",a==25);
}
}
I tried the solution using the code below, but It didn't pass.
Mockito.when(myClass.method2()).thenReturn(25);
Afterwards, Instead of the code snippet above, I tried something different and the test passed successfully. Take a look:
Mockito.doReturn(25).when(myClass).method2();
In order to mock a test (It might be a inner method), you have to use doReturn() method.
You can use doThrow(), doAnswer(), doNothing(), doReturn() and doCallRealMethod() in place of the corresponding call with when(), for any method. It is necessary when you
stub void methods
stub methods on spy objects (see below)
stub the same method more than once, to change the behaviour of a mock in the middle of a test.
but you may prefer to use these methods in place of the alternative
with when(), for all of your stubbing calls.
Furthermore information can be read here https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#12
Instead of using mock(class) here we need to use Mockito.spy() to mock the same class we are testing. Then we can mock the method we want as follows.
#Test
public void method1Test() {
MyClass myClass = new MyClass();
MyClass myClass1 = Mockito.spy(myClass);
Mockito.doReturn(1).when(myClass1).method2();
Assert.assertEquals(1, myClass1.method1());
}
}
I am trying to test a method whom depending on some conditions will execute its code or its super class's one.
Here is the code of the class and its parent:
public class ParentClass {
public Object doStuff(Parameters parameters) {
// do some business stuff
return parentResult;
}
}
The inherited class's one:
public class InheritedClass extends ParentClass {
#Override
public Object doStuff(Parameters parameters) {
if (parameters.getCondition()) {
return super.doStuff(parameters);
}
//do some business stuff
return inheritedResult;
}
}
So, when trying to test the case when the parameters.getCondition() is true, I have to mock the call on the super method and verify it.
But when I do this (mocking the call for the super.doStuff()), I also mock the call to the InhertitedClass.doStuff().
Here's the solution I tried:
#RunWith(MockitoJUnitRunner.class)
public class InheritedClassTest {
#Mock
private Parameters parameters;
#Spy
private InheritedClass inherited = new InheritedClass();
#Test
public void testDoStuff(Object parameters) throws Exception {
given(parameters.getCondition()).willReturn(true);
doCallRealMethod().doReturn(value).when(inherited).doStuff(parameters);
Mockito.verify(inherited, times(2)).doStuff(parameters);
}
}
I also tried this stubbing:
when(inherited.doStuff(parameters)).thenCallRealMethod().thenReturn(value);
and this one:
given(((ParentClass)inherited).doStuff(parameters)).willReturn(value);
In all this cases, the code of the parent class was really executed.
So, I was wondering if there is any efficient way to mock the call of the super class method using mockito?
You can use Mockito's spy(), which you already tried to do. But I think a different way of using spy() will make it work.
ParentClass.java
public class ParentClass {
public String doStuff(final String parameters) {
return "parent";
}
}
InheritedClass.java
public class InheritedClass extends ParentClass {
#Override
public String doStuff(final String parameters) {
if (parameters.equals("do parent")) {
return super.doStuff(parameters);
}
return "child";
}
}
InheritedClassTest.java
public class InheritedClassTest {
#Test
public void testDoStuff() throws Exception {
final InheritedClass inheritedClass = Mockito.spy(new InheritedClass());
Mockito.doReturn("mocked parent").when((ParentClass)inheritedClass).doStuff(Mockito.eq("do parent"));
final String result = inheritedClass.doStuff("do parent");
assertEquals("mocked parent", result);
assertNotEquals("parent", result);
final String resultChild = inheritedClass.doStuff("aaa");
assertEquals("child", resultChild);
}
}
However, I do not think using spy() is a good practice. I would personally refactor your code.
Suppose we have the following code:
class Test {
private Test() {
System.out.println("test");
}
}
public class One extends Test {
One() {
System.out.println("One");
}
public static void main(String args[]) {
new One();
}
}
When we create an object One, that was originally called the parent class constructor Test(). but as Test() was private - we get an error.
How much is a good example and a way out of this situation?
There is no way out. You have to create an available (protected, public or default) super constructor to be able to extend test.
This kind of notation is usually used in utility classes or singletons, where you don't want the user to create himself an instance of your class, either by extending it and instanciating the subclass, or by simply calling a constructor of your class.
When you have a class with only private constructors, you can also change the class to final because it can't be extended at all.
Another solution would be having a method in test which create instances of test and delegate every method call from One to a test instance. This way you don't have to extend test.
class Test {
private Test() {
System.out.println("test");
}
public static Test getInstance(){
return new Test();
}
public void methodA(){
//Some kind of implementation
}
}
public class One {
private final Test test;
One() {
System.out.println("One");
test = Test.getInstance();
}
public void methodA(){
test.methodA();
}
public static void main(String args[]) {
new One();
}
}
Make the constructor of test non-private or move One into test.
BTW, your sample code contains a few issues:
classes should be named title case (Test instead of test)
I'd suggest to make the One's constructor private unless it is called from a different class in the same package
Actually, I found there is a way out. Like this:
class Base {
private Base() {
}
public void fn() {
System.out.println("Base");
}
public static class Child extends Base {
public void fn() {
System.out.println("Child");
}
}
public static Base getChild() {
return new Child();
}
}
Now, you can use getChild() to get instance of the extended class.