I am new to mockito. Lets say I have a class like this
public class MyClass {
int a;
String b;
public MyClass(int a) {
this.a = a;
this.b = draw();
System.out.println("class is created");
}
public String draw() {
System.out.println("my");
return "b";
}
public void apple() {
System.out.println("apple");
}
}
I am writing a JUnit test using Mockito where I am creating a object of the class by using the constructor. Is it possible to mock the draw() method when I am instating the class?
Not clear why you need the Mockito here. This is a solution without Mockito.
In your test create an instance of MyClass with overridden draw() method:
final MyClass myClass = new MyClass() {
#Override
public String draw() {
return "mock data";
}
}
// Now test your class as you want
You could turn to do partial mocking using spies (see here for how to do that).
But as usual: when people start thinking about complex ways to use mocking framework, the real answer is: step back and improve your production code. Your constructor should do only simple initialisation things.
In your case, one reasonable approach would be: don't call an internal method to compute the value of that field - but pass that value to the constructor (in other words - use dependency injection).
And you could still do something like:
public MyClass(int a) {
this(a, draw());
}
MyClass(int a, String b) {
this.a = a; ...
Now your unit tests can happily use that ctor that takes two arguments - and your need to mock anything vanishes completely.
One way to test your class with Mockito will be,
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
public class TestMyClass {
#Mock
private MyClass clazz;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testDraw() {
when(clazz.draw()).thenReturn("My mock hello");
assertEquals("My mock hello", clazz.draw());
}
}
Complementing the solutions given, the constructor can also receive the method to mock as a function.
import java.util.function.Supplier;
public class MyClass {
int a;
String b;
public MyClass(int a, Supplier<String> draw) {
this.a = a;
this.b = draw==null? draw() : draw.get();
System.out.println("class is created");
}
public String draw() {
System.out.println("my");
return "b";
}
public void apple() {
System.out.println("apple");
}
}
Related
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();
}
I am writing unit test for a class A, I want to mock a method but that method is benign called from a class level object, How i will mock this.
Let me explain it from example
Class A which is under test.
public class ClassA {
ClassB objectOfB = new ClassB();
public int add(int a, int b) {
int addition = objectOfB.performCalculation(a,b);
return addition;
}
}
Class B, which has some business logic.
public class ClassB {
public int performCalculation(int a, int b) {
int c = a+b;
System.out.println("I am not mocked, I am actual call");
System.out.println("Returning " + c + " From ClassB");
return c;
}
}
Test Written
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassA.class, ClassB.class})
public class ClassATest {
#InjectMocks
ClassA objA = new ClassA();
#Test
public void testAddFromClassA() throws Exception {
ClassB objB = Mockito.mock(ClassB.class);
Mockito.when(objB.performCalculation(5, 10)).thenReturn(15);
int result = objA.add(5, 10);
assertEquals(result, 15);
}
}
Test Result:
This test is pass, but it is not mocking ClassB's method, instead it is performing actual call.
Requirement:
While writing test, i want to mock line : objectOfB.performCalculation(a,b); from class A, but as you can see object of classB() is created on class level.
How I can mock this?
What i should write in my test class.
Mock the initialization of the class so that the mock is used when exercising the test
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassA.class}) //prepare the class creating the new instance of ClassB for test, not the ClassB itself.
public class ClassATest {
#Test
public void testAddFromClassA() throws Exception {
int expected = 15;
ClassB objB = Mockito.mock(ClassB.class);
Mockito.when(objB.performCalculation(5, 10)).thenReturn(expected);
//mocking initialization of ClassB class withing ClassA class
PowerMockito.whenNew(ClassB.class).withNoArguments().thenReturn(objB);
ClassA objA = new ClassA();
//Act
int actual = objA.add(5, 10);
//Assert
assertEquals(expected, actual);
}
}
Reference How to mock construction of new objects
Now with that said, ideally the target class should follow explicit dependency principle via constructor injection
public class ClassA {
final ClassB objectOfB;
public ClassA(ClassB objectOfB) {
this.objectOfB = objectOfB;
}
public int add(int a, int b) {
int addition = objectOfB.performCalculation(a,b);
return addition;
}
}
The allows the class to explicitly state what it depends on to perform its designed function.
It also allows for inversion of control and loose coupling, which makes the class more flexible to maintain and test
#RunWith(PowerMockRunner.class)
public class ClassATest {
#Test
public void testAddFromClassA() throws Exception {
int expected = 15;
ClassB objB = Mockito.mock(ClassB.class);
Mockito.when(objB.performCalculation(5, 10)).thenReturn(expected);
ClassA objA = new ClassA(objB);
//Act
int actual = objA.add(5, 10);
//Assert
assertEquals(expected, actual);
}
}
Just because PowerMockito allows for the mock construction of new objects does not mean that we should.
If proper design principles are followed, then there really is no need for such hacks.
I would suggest reading a little more about mocking and how it is done.
Look in the test code you tried to run :
ClassB objB = Mockito.mock(ClassB.class);
Mockito.when(objB.performCalculation(5, 10)).thenReturn(15);
int result = objA.add(5, 10);
assertEquals(result, 15);
What is going on .
You are mocking ClassB but you are not using the mocked instance objB.
When you are mocking a class, you get back a mocked instance , this doesn't mean the class is now mocked throught your test, it just mean that you can use Mockito to manipulate this specific instace.
What should be going on .
If you can't use that instance to test a method is dependent on it, like in your case, that means you have a very strong dependency between those two classes, and if that is a problam for your tests that usually means your design is faulty. you should be able to inject ClassA into ClassB, either by suppling it an argument in the constructor
public ClassA(ClassB bInstance){
this.bIntance = bInstance
}
or, if that makes since for the specific action, as a function argument.
public add(ClassB classBInstance, int a, int b){
classBInstance. performCalculation(a.b)
}
This will allow you to mock an instance and run ClassA function with the specific implenetation you mocked:
ClassB classBInstance1 = Mockito.mock(ClassB.class)
ClassB classBInstance2 = Mockito.mock(ClassB.class)
Mockito.when(classBInstance1.performCalculation(5, 10)).thenReturn(15);
Mockito.when(classBInstance2.performCalculation(5, 10)).thenReturn(42);
new ClassA(classBInstance1).add(5,10) //returns 15
new ClassA(classBInstance2).add(5,10) //returns 42
new ClassA().add(classBInstance1,5,10) //15
new ClassA().add(classBInstance2,5,10) //42
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());
}
}
Please provide minimal examples of using PowerMockito to test public, public static, private, and private static methods.
Here's an extremely stripped down example ("SSCCE") of using PowerMockito to verify four types of methods have been called from another method: public, public static, private, and private static.
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(com.dnb.cirrus.core.authentication.TestableTest.Testable.class)
public class TestableTest {
public static class Testable {
public void a() {
b();
c();
d();
e();
}
public void b() {
}
public static void c() {
}
private void d() {
}
private static void e() {
}
}
Testable testable;
// Verify that public b() is called from a()
#Test
public void testB() {
testable = Mockito.spy(new Testable());
testable.a();
Mockito.verify(testable).b();
}
// Verify that public static c() is called from a()
#Test
public void testC() throws Exception {
PowerMockito.mockStatic(Testable.class);
testable = new Testable();
testable.a();
PowerMockito.verifyStatic();
Testable.c();
}
// Verify that private d() is called from a()
#Test
public void testD() throws Exception {
testable = PowerMockito.spy(new Testable());
testable.a();
PowerMockito.verifyPrivate(testable).invoke("d");
}
// Verify that private static e() is called from a()
#Test
public void testE() throws Exception {
PowerMockito.mockStatic(Testable.class);
testable = new Testable();
testable.a();
PowerMockito.verifyPrivate(Testable.class).invoke("e");
}
}
Some pitfalls to be aware of:
PowerMockito and Mockito both implement spy() as well as other methods. Make sure to use the correct class for the situation.
Incorrectly set up PowerMockito tests often pass. Be sure the test can fail when it should (checked for in the above code by commenting out "testable.a()").
Overridden PowerMockito methods take either Class or Object as parameters which are used in static and non-static contexts respectively. Make sure to use the correct type for the context.
I'm trying to write unit tests with Mockito / JUnit for a function like this:
class1 {
method {
object1 = class2.method // method that I want to fake the return value
// some code that I still want to run
}
}
Is there any way in Mockito to stub the result of class2.method? I'm trying to improve code coverage for class1 so I need to call its real production methods.
I looked into the Mockito API at its spy method but that would overwrite the whole method and not the part that I want.
I think I am understanding your question. Let me re-phrase, you have a function that you are trying to test and want to mock the results of a function called within that function, but in a different class. I have handled that in the following way.
public MyUnitTest {
private static final MyClass2 class2 = mock(MyClass2.class);
#Begin
public void setupTests() {
when(class2.get(1000)).thenReturn(new User(1000, "John"));
when(class2.validateObject(anyObj()).thenReturn(true);
}
#Test
public void testFunctionCall() {
String out = myClass.functionCall();
assertThat(out).isEqualTo("Output");
}
}
What this is doing is that within the function wrapped with the #Before annotation, I am setting up how I want the functions in class2 to respond given specific inputs. Then, from within the actual test, I am just calling the function that I am trying to test in the class I want to test. In this case, the myClass.functionCall() is running through as normal and you are not overwriting any of its methods, but you are just mocking the outputs that it gets from the methods (or method) within MyClass2.
This Worked for Me:
public class Class1Test {
Class1 class1;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
class1 = new Class1();
}
#Test
public void testClass1Method() {
Class2 class2 = Mockito.mock(Class2.class);
class1.setClass2(class2);
Mockito.when(
class2.class2Method(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn("some response");
String actualResponse = class1
.class1Method("12345", "3333", "4444");
assertEquals("some response", actualResponse);
}
}
I wrote a simple example which worked fine, hope it helps:
method1() from Class1 calls method2() from Class2:
public class Class1 {
private Class2 class2 = new Class2();
public int method1() {
return class2.method2();
}
}
Class2 and method2() :
public class Class2 {
public int method2() {
return 5;
}
}
And the Test:
import org.junit.Rule;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
public class TestClass1 {
#Mock
Class2 class2;
#InjectMocks
Class1 class1;
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Test
public void testMethod1(){
when(class2.method2()).thenReturn(29);
assertEquals(29,class1.method1());
}
}