Using Mockito to mock a class method inside another class - java

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());
}
}

Related

How to implement doNothing() for static void method?

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.

Mockito - Verifying if a method calls another method within the same class

I am trying to test whether a method calls another method within the same class. Example:
public class Foo {
public void bar(String a){
switch(a) {
case "callBaz":
baz(a);
break;
case "callBat":
bat(a);
break;
default:
System.out.println("Input was " + a);
}
}
public void baz(String b){
System.out.println(b);
}
public void bat(String c){
System.out.println(c);
}
}
However if I try mockito verify on the class itself:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
public class FooTest {
#Test
public void testBazCalledFromBar(){
Foo foo = new Foo();
foo.bar("callBaz");
Mockito.verify(foo).baz("callBaz");
}
}
I get the exception:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type Foo and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
When using the mock:
...
#RunWith(SpringJUnit4ClassRunner.class)
public class FooTest {
#Test
public void testBazCalledFromBar(){
Foo fooMock = Mockito.mock(Foo.class);
fooMock.bar("callBaz");
Mockito.verify(fooMock).baz("callBaz");
}
}
I get the exception:
Wanted but not invoked:
foo.baz("callBaz");
-> at com.mn.stagportal.view.employee.FooTest.testBazCalledFromBar(FooTest.java:15)
However, there were other interactions with this mock:
foo.bar("callBaz");
-> at com.mn.stagportal.view.employee.FooTest.testBazCalledFromBar(FooTest.java:13)
Does anyone know how to test if baz("callBaz") is called?
This should work.
#RunWith(SpringJUnit4ClassRunner.class)
public class FooTest {
#Test
public void testBazCalledFromBar(){
Foo fooMock = Mockito.mock(Foo.class);
doCallRealMethod().when(fooMock).bar(anyString());
fooMock.bar("callBaz");
Mockito.verify(fooMock).baz("callBaz");
}
}
The issue is, since fooMock is a mock, when it encounters this line
fooMock.bar("callBaz");
It doesn't know what to do. You need to tell Mockito, whether you want to mock the method call or you want to call the real method.
Verify can only work if the code flow goes to this real method and called the baz method.
You shouldn't mock the tested object, you can spy instead:
#RunWith(SpringJUnit4ClassRunner.class)
public class FooTest {
#Test
public void testBazCalledFromBar(){
Foo foo = Mockito.spy(Foo.class);
foo.bar("callBaz");
Mockito.verify(foo).baz("callBaz");
}
}
or
#RunWith(SpringJUnit4ClassRunner.class)
public class FooTest {
#Test
public void testBazCalledFromBar(){
Foo foo = Mockito.spy(new Foo(/* params */));
foo.bar("callBaz");
Mockito.verify(foo).baz("callBaz");
}
}

PowerMockito.whenNew is not working

Hi folks i am new to PowerMockito and i am trying to use whenNew in PoweMockito and its not working for me, can anyone please help me out with this??
Below is my Test method which is used to test Class2, and i have Used PowerMockito.whenNew for mocking mockTestMethod inside Class2 and return String Value as "MOCKED VALUE" but that is not happening and actually the method is being executed and output is "PassedString".
If i am not wrong the Output should have string as "Inside Class2 method MOCKED VALUE" but i am getting output as "Inside Class2 method PassedString."
Please help me with the issue,
Thanks In Advance.
Below is the complete program which i am working on
package com.hpe.testing2;
public class Class2 {
public void testingMethod(){
Class1 class1 = new Class1();
String result = class1.mockTestMethod("PassedString");
System.out.println("Inside Class2 method " + result);
}
}
package com.hpe.testing2;
public class Class1 {
public String mockTestMethod(String str2){
String str1="SomeString";
str1 = str2;
System.out.println("Inside MockTest Method " + str1);
return str1;
}
}
class2 is invoking Class1 mockTestMethod internally as shown above.
package com.hpe.testing2;
import org.junit.runner.RunWith;
import org.mockito.Mock;
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({Class2.class,Class1.class})
public class ClassTest {
public static void main(String[] args) throws Exception {
ClassTest testing = new ClassTest();
testing.runMethod();
}
public void runMethod() throws Exception{
Class2 class2 = new Class2();
Class1 class1 = PowerMockito.mock(Class1.class);
PowerMockito.whenNew(Class1.class).withAnyArguments().thenReturn(class1);
PowerMockito.when(class1.mockTestMethod(Mockito.anyString())).thenReturn("MOCKED
VALUE");
class2.testingMethod();
}
}
You cannot start a test class via main method. Instead it should be run with JUnit. Therefore a #Test annotation has to be present at the test method. Look here for getting started with JUnit.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Class2.class, Class1.class })
public class ClassTest {
#Test
public void runMethod() throws Exception {
Class2 class2 = new Class2();
Class1 class1 = PowerMockito.mock(Class1.class);
PowerMockito.whenNew(Class1.class).withAnyArguments().thenReturn(class1);
PowerMockito.when(class1.mockTestMethod(Mockito.anyString())).thenReturn("MOCKED VALUE");
class2.testingMethod();
}
}
(I left out imports in your testclass)

How to mock a call of an inner method from a Junit

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());
}
}

How To Set Up PowerMockito To Verify Different Types of Methods Are Called?

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.

Categories

Resources