Consecutive calls testing in Mockito - java

I have simple service
package net.betlista;
import java.util.List;
public class MyServiceImpl implements MyService {
MyDao dao;
public void saveAll(final List<Integer> list) {
for (final int i : list) {
dao.save(i);
}
}
void setDao(final MyDao dao) {
this.dao = dao;
}
}
and DAO
package net.betlista;
public class MyDaoImpl implements MyDao {
public void save(final Integer i) {
// do nothing, ok for tests
}
}
and I want to test with Mockito that when I call service.saveAll(), that save() call is called for all instances in list:
package net.betlista;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;
public class MyServiceTest {
#Test
public void test() {
final MyDao daoMock = Mockito.mock(MyDao.class);
final MyServiceImpl service = new MyServiceImpl();
service.setDao(daoMock);
final List<Integer> list = new LinkedList<Integer>();
list.add(1);
list.add(2);
service.saveAll(list);
// not working, it's ok, should fail
// Mockito.verify(daoMock).save(Matchers.eq(1));
// Mockito.verify(daoMock).save(Matchers.eq(1));
final InOrder inOrder = Mockito.inOrder(daoMock);
inOrder.verify(daoMock).save(1);
inOrder.verify(daoMock).save(1); // change 1 to 2 to fix test
Mockito.verify(daoMock);
}
}
the commented part is not working = it passes, but should fail.
Using InOrder, works but in fact I'm not interested in order (for example if using set instead of list, order is not known).
Any idea, or I'm just trying to do something senseless?

The best way to do this is with an ArgumentCaptor.
service.saveAll(list);
ArgumentCaptor<Integer> values = ArgumentCaptor.forClass(Integer.class);
verify(daoMock, times(list.size())).save(values.capture());
assertEquals(list, values.getAllValues());
The ArgumentCaptor gives you access to all of the values that were ever passed to this method. So there's no need to worry about whether this method was called "extra" times; and no problem in the case where the same value occurs twice in the original list.

I want to test with Mockito that when I call service.saveAll(), that save() call is called for all instances in list
OK, then how about this:
service.saveAll(list);
for (int i:list)
{
Mockito.verify(daoMock).save(Matchers.eq(i));
}
I'm not entirely sure why you think the commented out lines should fail, but I'm guessing that its because you want to make sure its only called once? If so, then the reason it passes it because it has only been called once, however, your test code is verifying twice that it was only called once which isn't much use. The above code will verify that the save method was called once (and only once) for each item in the list.

Mockito.verify(daoMock, Mockito.times(2)).save(Matchers.eq(1));
Since you are verifying the same value, use times()
However, the better way to test that there are exactly the number of invocations you want is to use verifyNoMoreInteractions
So the test would be like this:
verify(daoMock).save(1);
verify(daoMock).save(2);
verifyNoMoreInteractions(daoMock);

Related

How to capture incoming parameters with EasyMock.capture?

I'm testing a class and wanted to monitor calls to a specific method, namely to save the calling parameters for later analysis.
Testing is done with EasyMock, so it was logical to use EasyMock.capture feature. However, the examples that I managed to find do not work for me - I get the following compile error at the line with capture:
expect(T) in EasyMock cannot be applied to (void)
reason: no instance of type variable T exist so that void conforms to T
It would be great if somebody could point out my mistake(s) for me. Below is a code snippet:
import static org.easymock.EasyMock.capture;
import org.easymock.Capture;
import org.easymock.CaptureType;
import org.easymock.EasyMock;
import org.junit.Before;
class B {
}
class A {
public void doSomething(B input) {
}
}
public class ATest {
private Capture<B> capturedData;
private A testObject;
#Before
private void setUp() {
capturedData = EasyMock.newCapture(CaptureType.ALL);
testObject = EasyMock.createNiceMock(A.class);
EasyMock
.expect(testObject.doSomething(capture(capturedData)))
.anyTimes();
}
}
Thanks a lot in advance!
Your problem is not related to the capture, but to the return type of your doSomething() method:
Since A.doSomething(B input) is of return type void, you don't expect the method to return anything, thus you cannot use EasyMock.expect() for it. Instead, simply invoke the method and use EasyMock.expectLastCall(), like so:
testObject.doSomething(capture(capturedData));
EasyMock.expectLastCall().anyTimes();
EasyMock.expectLastCall() declares that you expect the last method invocation before expectLastCall() to be executed. You can then handle it just like expect(), e.g. add anyTimes() to it.

Powermock not intercepting new object creation

I am attempting to test a method that creates a new instance of another class that I wish to mock using powermock. My code (simplified) is as follows -
Testing code:
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.easymock.EasyMock.anyObject;
import static org.powermock.api.easymock.PowerMock.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest( { ClassUnderTest.class } )
public class TestForClassUnderTest {
private ClassToBeMocked classToBeMocked;
private ClassUnderTest classUnderTest;
public void testSimple() throws Exception {
classToBeMocked = createMock(ClassToBeMocked.class);
// trying to intercept the constructor
// I *think* this is the root cause of the issue
expectNew(ClassToBeMocked.class, anyObject(), anyObject(), anyObject()).andReturn(classToBeMocked);
classToBeMocked.close();
expectLastCall();
replayAll();
// call to perform the test
classUnderTest.doStuff();
}
}
Code that is being tested:
import ClassToBeMocked;
public class ClassUnderTest {
private ClassToBeMocked classToBeMocked;
public void doStuff() {
classToBeMocked = new ClassToBeMocked("A","B","C");
// doing lots of other things here that I feel are irrelevant
classToBeMocked.close();
}
}
Code that I wish to mock:
public class ClassToBeMocked {
public ClassToBeMocked(String A, String B, String C) {
// irrelevant
}
public close() {
// irrelevant
}
}
The error I get is as below:
java.lang.ExceptionInInitializerError
at ....more inner details of where this goes into
at ClassToBeMocked.close
at ClassUnderTest.doStuff
at TestForClassUnderTest.test.unit.testSimple
Caused by: java.lang.NullPointerException
PowerMock version:1.4.5
EasyMock version: 3.1
PS: I have stripped down the code to bare minimums, only showing the details of the mocking library, let me know if you think my other code is somehow interfering and I can give more details on the bits you think are important to show. Any links to other examples doing this may even help.
I realized that the reason this wasn't working was because I was extending another class. I had
#RunWith(PowerMockRunner.class)
#PrepareForTest( { ClassUnderTest.class } )
public class TestForClassUnderTest extends AnotherClass {
}
as soon as I removed the extends, it worked. Not sure if its just not able to extend another class with powermock or due to AnotherClass, but removing it worked for me
whenever you wish to mock a new instance of any class, you should be doing like this
Powermock.expectNew(ClassYouWishToMock.class).andReturn(whateverYouWantToReturn).anyTimes();
Powermock.replayAll();
this will return 'whateverYouWantToReturn' whener new is called on this class.
but whenever you want to mock a instance variable, you should be using Whitebox feature of easymock.
have a look at following Example
Class A{
private B b;
}
to mock this my test class will look something like this
...//other powermock, easymock class level annotations
#PrepareForTest(B.class)
class ATest{
Whitebox.setInternalState(B.class,b,whateverValueYouWantYourMockedObjectToReflect);
}
here 'b' passed in parameter, is the variable name you want to mock.
Good Luck!

Is it possible to invoke mocked object's method?

I have, for example, this class:
public class A {
private List<String> list;
public A(B b){
list = b.getList();
}
public List<String> someMethod(){
return list;
}
}
I want to unit test someMethod without invoking constructor. I use reflection to set list.
The problem is that I don't want to create B class object and I cannot mock it since it will cause NPE.
So my question is:
How to test someMethod without calling constructor of A? Is there any way to mock class A and doesn't lose posibility to call methods?
Creating constructor with zero arguments is not a solution.
Note: I don't want to change any part of A class. I'm asking if it is possible to perform this test without adding or changing anything in A class.
You can test class A without calling it's constructor by Mockito. Not sure if I really understand your requirement but the following codes work for me.
import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ATest {
#Test
public void test() {
A a = mock(A.class);
when(a.someMethod()).thenCallRealMethod();
List<String> listInA = new ArrayList<String>();
ReflectionTestUtils.setField(a, "list", listInA);
assertThat(a.someMethod(), is(listInA));
}
}
You should mock out the collaborators to your class -- that means that you can create an instance of the class being tested, and pass in mocks, configured to 'do the right thing' when it's methods are called.
In your example, you want to create a mock B, and use it like this:
#RunWith(MockitoJUnitRunner.class)
class myTest {
#Mock private B b;
public void someMethod() {
doReturn(new ArrayList<String>()).when(b).getList();
A a = new A(b);
assertEquals("result", a.someMethod().get(0));
}
}
I don't want to create B class object
Add a constructor or factory method which doesn't require a B.
public A(B b){
this(b.getList());
}
/* package local */ A(List<String> list){
this.list = list;
}
By making the constructor package local it can be accessed by unit tests in the same package.
How to test someMethod without calling constructor of A?
You can use
A a = theUnsafe.allocateInstance(A.class);
but this is not recommended unless you have no other option e.g. deserialization.

Mockito argument to a private method

This is my sample service class:
class Service {
#Inject
private TestDao dao;
public void method() {
//Other logic
List<SomeClass> list = new ArrayList<SomeClass>();
privateMethod(list);
//Other logic
}
private void privateMethod(List<SomeClass> list) {
dao.save(list);
}
}
If I mock dao using Mockito, then how can I test the number of calls to dao.save method? When I tried with verify, I have to give the list object. But I am not seeing any way to get that object.
Any thoughts?
You can use the anyList() matcher if you don't care about exactly what list your method is being called with. For example, if you want to verify the save() method was called exactly thrice:
verify(dao, times(3)).save(anyList())
If you want to make further assertions about what list save() was called with, use ArgumentCaptor
An example usage of ArgumentCaptor:
ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class);
verify(dao, times(3)).save(argument.capture());
List secondValue = argument.getAllValues().get(1); // captured value when the method was called the second time
Call verify with Matchers.anyList():
verify(dao).save(Matchers.anyList());

JUnit instantiating object every time a test case method runs

Test case:
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class PendingTest {
PendingUtil pendingUtil = new PendingUtil();
boolean result;
#Test
public void fetchPendingWFFromDB(){
result = pendingUtil.fetchPendingWFFromDB();
assertTrue(result);
}
#Test
public void runPendingBatch() {
result = pendingUtil.runPendingBatch();
assertTrue(result);
}
#Test
public void checkQueuePostPendingRun() {
result = pendingUtil.checkQueuePostPendingRun();
assertTrue(result);
}
}
Class called from JUnit test case.
public class PendingUtil {
public PendingUtil() {
try {
System.out.println("In Const");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
In my test case I only create the object once:
PendingUtil pendingUtil = new PendingUtil();
But internally JUnit calls the constructor three times.
Why is this happening?
You've annotated 3 methods with #Test. From the JUnit API doc on this annotation: To run the method, JUnit first constructs a fresh instance of the class then invokes the annotated method.
In short, the entire test class is instanced 3 times, and therefore, so is PendingUtil (once from each subsequent instance of the test class).
To do what you want, keep the property definition where it is, but assign the PendingUtil instance to it in a new method annotated with the #BeforeClass annotation.
Additionally, you could mark the property as static as suggested by vikingsteve.
You could create the pendingUtil in a #BeforeClass method.
Hey just for update with Junit5,
You could create the pendingUtil in a #BeforeAllmethod.
or like below:
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class PendingTest {
}
Just for sake of knowledge, we can make that Lifecycle.PER_METHOD if we need to create fresh instance per method.
Conversely if you do not want the PendingUtil to be called thrice you should probably write a TestUtil wrapper which probably just puts a Factory method in front of new PendingUtil() and only creates one instance.
You could make pendingUtil static
static PendingUtil pendingUtil = new PendingUtil();

Categories