Proper usage of Mockito.verify - java

I'm new to unit testing and i had a simple question regarding the usage of verify method used in Mockito. here's the class i used for testing.
public class Foo{
int n = 0;
void addFoo(String a){
if(a == "a")
add(1);
}
protected void add(int num){
n =1;
}
public int get(){
return n;
}
}
And here's my Unit test.
public class FooTest {
#Mock Foo f;
#Test
public void test() {
MockitoAnnotations.initMocks(this);
f.addFoo("a");
//Passes
Mockito.verify(f).addFoo("a");
//Fails
Mockito.verify(f).add(1);
}
}
And i get a
Wanted but not invoked:
f.add(1);
-> at FooTest.test(FooTest.java:22)
However, there were other interactions with this mock:
-> at FooTest.test(FooTest.java:16)
exception.
How do you verify that add(int num) is called ?

I think you misunderstood the point of verify.
In your test, Foo f is a mock object - Foo's internal implementation is ignored, and only the behavior you recorded on it (using when(f.someMethod().thenXXX) would happen.
The point of mocking and verifying is to test interactions while ignoring the internal implementation.
In this example, you would probably have another class that uses Foo, and you'd want to test whether it invokes the correct methods of the given Foo instance.
Quick example:
Assume you have a class the uses the Foo class you presented in your question:
public class FooUser {
private Foo f;
public void setFoo(Foo f) {
this.f = f;
}
public Foo getFoo() {
return f;
}
public void addToFoo(String string) {
f.add(string);
}
}
Now, you'd want to test that FooUser#addToFoo(String) indeed invokes the correct add(String) method of Foo:
#RunWith (MockitoJUnitRunner.class)
public class FooUserTest {
#Mock Foo f;
FooUser fUser;
#Before
public void init() {
fUser = new FooUser();
fUser.setFoo(f);
}
#Test
public void test() {
fUser.addToFoo("a");
Mockito.verify(f).addFoo("a");
}

Related

How do you test method from extended class using Mockito?

I have a class A that extends from B. B has method called doB().
In my test, I want to return A when doB() is called.
Class B:
public String doB() {
return "B";
}
Class A:
public class A extends B {
public String doA() {
String A = doB();
return A;
}
}
In my unit test, I want to do something like:
#Mock
private A a;
#Test
public void test() {
when(a.doB()).thenReturn("PASS");
a.doB();
//check if it is "PASS"
}
However, it doesn't intercept when it calls doB(). Is this possible? If not, what is the best way to test this?
Perhaps favour composition over inheritance. In other words, instead of A extending B, A should use B. So B becomes A's collaborator.
For example:
public class B {
public String doB() {
return "B";
}
}
public class A {
private B b;
public A(B b) {
this.b = b;
}
public String doA() {
String a = b.doB();
return a;
}
}
So your unit test would look something like:
public class MyTest {
#Mock
private B b;
#InjectMocks
private A a;
#Test
public void test() {
when(b.doB()).thenReturn("PASS");
a.doA();
//check if it is "PASS"
}
}
This is an example of how TDD can contribute to good design.
Since you are mocking class A, the method will not really be executed, which means there is no call to doB inside youre mock execution.
you should either setup your mock to call the real method
when(a.doA()).thenCallRealMethod();
verify(a,times(1)).doB();
or use a Spy instead of a Mock.

How to mock method calls of some object which is passed as method parameter of method under JUnit Test

I am writing JUnit for some legacy class which I can't change. The Problem which I am facing is as follows
public class B{
public String method2() {
//fetch some data from database and return it
}
}
public class A{
public String myMethod(B b) {
return b.method2();
}
}
how can I mock the call for method2 in junit using mockito
public class B2 extends B { // so, this is, in fact, an IS-A of B
public String method2() {
return "mockedResult";
}
}
In your test, you'll now have something like this:
#Test
public void testMethod() {
A toTest = new A();
assertEquals("mockedResult", toTest.myMethod(new B2());
}
This is the very simplistic way. But I would recommend to read up on a Mocking framework, such as Mockito for more complex scenario's.
https://www.baeldung.com/mockito-series
By using Mockito, for short, it would be something like this:
public class TestClass {
#Mock
private B b;
private A toTest = new A();
#Test
public void testMethod() {
when(b.method2()).thenReturn("mockedResult");
assertEquals("mockedResult", toTest.myMethod());
}
}

Evaluate parameter passed to mocked method called from another class

I am testing a class that use another class I have mocked. One of the outer classes' methods modifies an argument that is passed to the mocked class's method, and I need to check that it was modified correctly.
The code looks something like this:
public class Foo
{
public boolean performTask(String name, Integer version)
{
...
}
}
public class Bar
{
private Foo foo;
public Bar(Foo foo)
{
this.foo = foo;
}
public void doSomething(String name, Integer version)
{
boolean good = foo.performTask(name, ((version.startsWith("A")) ? null : version));
...
}
}
I need to check that if I pass a name argument that starts with A, then the second argument being passed to performTask() is null.
Edit:
As requested, this the start of the unit test:
public class BarTest
{
#Mock
private Foo mockFoo;
#Before
public void setup() throws Exception
{
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception
{
Bar bar = new Bar(mockFoo);
bar.doSomething("ABC", new Integer(1));
}
}
All the examples I've seen of using verify involve calling the mock class directly. How do I use it in this case?
Exactly like that. All you need is access to the mock, which you have.
Mockito.verify(mockFoo, Mockito.times(1)).performTask("ABC", null);
If its important what the method is supposed to return (by default false),
you will need to define the behaviour using:
Mockito.when(mockFoo.performTask("ABC", null)).thenReturn(true);
Example:
#Test
public void test() throws Exception {
Mockito.when(mockFoo.performTask("ABC", null)).thenReturn(true);
Bar bar = new Bar(mockFoo);
bar.doSomething("ABC", new Integer(1));
Mockito.verify(mockFoo, Mockito.times(1)).performTask("ABC", null);
}

Mocked value is not returned

I have two classes:
public class Foo {
public int getInt(){
return 10;
}
}
public class Bar {
Foo testClass = new Foo();
public Foo getTestClass() {
return testClass;
}
public void setTestClass(Foo testClass) {
this.testClass = testClass;
}
public int get(){
return testClass.getInt();
}
}
And finally I have test class with mock for Foo:
public class TestClass {
Foo test;
#Before
public void init(){
test = Mockito.mock(Foo.class);
Mockito.when(test.getInt()).thenReturn(5);
}
#Test
public void tst(){
Bar t = new Bar();
Assert.assertEquals(t.get(), 5);
}
}
Could you tell me, why I'm getting 10 from t.get() although in mock "I say" that I want 5 ?
How can I write Mock to get mocking value?
Thanks in advance.
You forgot to actually set your mock with a call to t.setTestClass(test);.
When you're writing :
public class TestClass {
Foo test;
#Before
public void init(){
test = Mockito.mock(Foo.class);
Mockito.when(test.getInt()).thenReturn(5);
}
#Test
public void tst(){
Bar t = new Bar();
Assert.assertEquals(t.get(), 5);
}
}
You are mocking your Foo class, but not using it in the Bar class. So if you call the return method, it won't send the result you tried to mock

How to replace method invocation with mock?

I have a class with two methods. I want to replace invocation of second method with expected result.
Here is my class under test
public class A {
public int methodOne() {
return methodTwo(1);
}
public int methodTwo(int param) {
// corresponding logic replaced for demo
throw new RuntimeException("Wrong invocation!");
}
}
And test
public class ATest {
#Test
public void test() {
final A a = spy(new A());
when(a.methodTwo(anyInt())).thenReturn(10);
a.methodOne();
verify(a, times(1)).methodTwo(anyInt());
}
}
Why I'm get an exception when start the test?
Two things that will help you here. First, from the documentation it seems you need to use the do*() api with spy() objects. Second, to call the "real" method you need to declare it specifically using doCallRealMethod()
Here's the updated test that should work for you:
public class ATest {
#Test
public void test() {
final A a = spy(new A());
doReturn(10).when(a).methodTwo(anyInt());
doCallRealMethod().when(a).methodOne();
a.methodOne();
verify(a, times(1)).methodTwo(anyInt());
}
}

Categories