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");
}
}
Related
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");
}
}
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());
}
}
I have try following code:
package ro.ex;
/**
* Created by roroco on 11/11/14.
*/
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.mockito.Mockito.*;
public class ExTest extends junit.framework.TestCase {
class C {
public String m() {
return null;
}
}
public void testM() throws Exception {
when(new C().m()).thenAnswer(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
return (String) args[0];
}
});
}
}
i hope i can change a real instance meth not a mock, but above code raise:
when() requires an argument which has to be 'a method call on a mock'.
my question is: how to fix it.
I assume this is a sample code you created to ask a question here but in real, C should be the class under test (not a class within your test).
Class MyClassToTest {
public String m() {...}
}
Now in your test, mock class C. #Mock C c and followed by when(c.m()).thenAnswer..... in the test method.
Not sure why you would need that, but you can use spy:
public void testM() throws Exception {
C c = Mockito.spy(new C());
// actual method
c.m();
// stubbed method
when(c.m()).thenAnswer(...);
}
Alternatively, you can mock the object, and call thenCallRealMethod() when needed.