Count indirect method calls Mockito - java

I'm having problems with counting method calls with Mockito. Problem is that the method whos calls I want to count is called in test class indirectly by other method. Here is the code:
public class ClassForTest {
private Integer value;
public void doSmth() {
prepareValue("First call");
prepareValue("Second call");
prepareValue("Third call");
System.out.println(value);
}
protected void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
}
And the test class:
public class ClassForTestTest extends TestCase {
#Test
public void testDoSmth() {
ClassForTest testMock = mock(ClassForTest.class);
doNothing().when(testMock).prepareValue(anyString());
testMock.doSmth();
verify(testMock, times(3)).prepareValue(anyString());
}
}
Having such exception:
Wanted but not invoked:
classForTest.prepareValue(<any>);
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:24)
However, there were other interactions with this mock:
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:21)
Any ideas please. Thanks in advance!

This will work. Using a spy calls the underlying method. Make sure value is initialized first.
#Test
public void testDoSmth() {
ClassForTest testMock = spy(new ClassForTest());
testMock.doSmth();
verify(testMock, times(3)).prepareValue(anyString());
}
public class ClassForTest {
private Integer value = 0;
public void doSmth() {
prepareValue("First call");
prepareValue("Second call");
prepareValue("Third call");
System.out.println(value);
}
protected void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
}

This is an indication that you need some refactoring to improve your design. A single class should be fully testable without needing to mock out pieces of it. Whatever pieces you feel need to be mocked out should be extracted into one or more collaborating objects. Don't fall into the trap of partial mocks. Listen to what the tests are telling you. Your future self will thank you.

You are mocking the tested class. Mocking is intended for the dependencies of a tested class, rather than the class itself.
I suspect what you want is Mockito.spy(). However, this is partial mocking which the Mockito Javadoc recommends against.

Alternatively, if you want to refactor for testability, you can do the following:
#Test
public void testDoSmth() {
Preparer preparer = mock(Preparer.class);
ClassForTest cft = new ClassForTest(preparer);
cft.doSmth();
verify(preparer, times(3)).prepareValue(anyString());
}
public class ClassForTest {
private final Preparer preparer;
public ClassForTest(Preparer preparer) {
this.preparer = preparer;
}
public void doSmth() {
preparer.prepareValue("First call");
preparer.prepareValue("Second call");
preparer.prepareValue("Third call");
System.out.println(preparer.getValue());
}
}
public class Preparer {
private Integer value = 0;
public void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
public Integer getValue() {
return value;
}
}

Related

mockito verifying polymorphic methods

I'm trying to verify call to a polymorphic method using mockito, and am confused about what the best way forward is.
Example Class
public class Library {
public boolean foo() {
return true;
}
public boolean foo(String s) {
return true;
}
public boolean foo(Integer s) {
return true;
}
}
The test class using mockito(ignore the fact that in LibraryTest class, Library is not the class-under-test, but rather I'm mocking it)
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class LibraryTest {
#Test public void testFoo1() {
Library mockLibrary = mock(Library.class);
mockLibrary.foo("Hi");
verify(mockLibrary).foo(any());
}
#Test public void testFoo2() {
Library mockLibrary = mock(Library.class);
verify(mockLibrary, never()).foo(any());
}
}
So both the verify statements don't compile, with the error "The method foo(String) is ambiguous for the type Library".
The error kind of makes sense, any() tries to return a captor based on the type of the argument but the argument could be Integer or String or void.
What I want to achieve is that in both the tests, a call to any of the foo methods is counted by the verify. In other words the first verify call should succeed if I called any of the foo methods and the second verify should fail if I call any of the foo methods.
Is there a way to make this happen?
You can use isA matcher
verify(mockLibrary).foo(isA(Integer.class));
verify(mockLibrary).foo(isA(String.class));
and btw use Mockito.spy instead of Mockito.mock when you only want to see if some methods have been called on the class under test
EDIT with example (written in few minutes, don't mind the code:)) based on the new op details.
public static class Library {
public boolean foo() {
return true;
}
public boolean foo(String s) {
return true;
}
public boolean foo(Integer s) {
return true;
}
public String x(){
return "";
}
public void y(){
return;
}
}
public static class ResponseProvider {
public boolean result;
}
#Test
public void testFoo1() {
final ResponseProvider provider = new ResponseProvider();
provider.result = false;
Library lib = Mockito.mock(Library.class, new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
if ((invocation.getMethod().getName().equals("foo"))) {
provider.result = true;
return true;
}
return invocation.callRealMethod();
}
});
//lib.foo();
//lib.x();
//lib.y();
assertTrue(provider.result);
}
First of all, You are mocking the same class which you are testing. Thats not advisable but still
Its giving this exception because mockito doesn't know which method you are verifying among the foo methods. If you want to make sure the method you invoked is called with the right value, you can either use isA(ClassName) matcher or use can use ArgumentCaptor.
Example of ArgumentCaptor
#Test public void testFoo1() {
Library mockLibrary = mock(Library.class);
mockLibrary.foo("Hi");
ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);
verify(mockLibrary).foo(stringCaptor.capture());
String actualArgument = stringCaptor.getValue();
assertEquals(actualArgument, "Hi");
}

How to modify/decorator an object returned from 3rd party API using javassist/CGLib

I have an 3rd party API call which returns the following object:
public class A {
protected void common() {
System.out.println("common is called in A");
}
public void test1() {
common();
System.out.println("test1 is called in A");
}
public void test2() {
common();
System.out.println("test2 is called in A");
}
}
But I'd like to modify its behavior like the following ModifiedA shows:
public class ModifiedA extends A {
#Override
protected void common() {
super.common();
System.out.println("common is called in ModifiedA");
}
}
So what I am trying to do is:
A a = 3rdPartyAPI_call();
//
// Now I'd like to get a ModifiedA which has changed common() behavior.
//
How to use javassist/CGLIB to accomplish this ?
One easy way may be to like this:
public class ModifiedA extends A {
private A a;
public ModifiedA(final A a) {
this.a = a;
}
//
// Override every public method in A
//
#Override
protected void common() {
super.common();
System.out.println("common is called in ModifiedA");
}
}
But since A's definition comes from 3rd party and is very complex and may change, so I'd like to use a proxy to do this?
Thanks for your comments in adavance.
You can use CGLib to implement a delegator pattern without having to override all the methods. There are a few different approaches to implement this depending on style but here is one similar to your example.
You can wrap the instance using a cglib Enhancer:
public static <T> T wrapInstance(final T original) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(original.getClass());
enhancer.setCallback(new MethodInterceptor() {
#Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object returnValue = proxy.invoke(original, args);
if (method.getName().equals("common")) {
System.out.println("common is called");
}
return returnValue;
}
});
return (T) enhancer.create();
}
eclps post will fullfill your requirement and it works.I want to add some more code to eclps code.
Adding filter which give index zero for common method and rest all method to One. MethodInterceptor callback will intercept only common method and rest all method use NoOp intercetor(which will call super class apis).This way filtering is not happening for every method call.
public static <T> T wrapInstance(final T original) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(original.getClass());
enhancer.setCallbackFilter(new CallbackFilter() {
#Override
public int accept(Method method) {
if (method.getName().equals("common")) {
return 0;
}
return 1;
}
});
enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
#Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// only common method will intercept this call back.
return proxy.invoke(this, args);
}
}, NoOp.INSTANCE});
return (T) enhancer.create();
}

JMockit: How to mock protected methods?

I'm trying to use JMockit in order to mock a protected method of a class:
public class A {
protected String say() {
return "hi";
}
}
public class B extends A {
public String cry() {
return "waaaa " + say();
}
}
I want to mock "say" method in my tests, so that every instance of B, when it invokes "say", it will get "bye" instead of "hi".
Thanks.
You can simply make a MockUp of A:
new MockUp<A> () {
#Mock protected String say() { return "bye"; }
};
System.out.println(new B().cry()); // prints waaaa bye

Setting up a test system with "real data"

So right now I'm using JUnit 4 and in the #BeforeClass methods I setup everything needed to reset the user schema or to prepare sample data.
Now, it's not that I don't like this approach but I found it quite frustrating for the following reason:
I'm using the Parameterized annotation to run the very same tests with different input data. Parameterized doesn't work on #BeforeClass because #BeforeClass works with a static method.
This means I have to replicate tests if I want to keep the #BeforeClass logic. I can't use #After and #Before because those will happen after every test and it would be an overhead.
I was thinking I could refactor this Unit Tests in the sense that I'll write an abstract class that handles the test and a subclass for every group parameters I want to try so that I can have the test code written only once.
I'm hoping you can suggest a cleaner option with the following starting point: the use of #Parameterized, the need to run the "database" method only once per parameter group.
EDIT:
this is an example of my class without the BeforeClass
RunWith(LabelledParameterized.class)
public class TestCreateCampaign extends AbstractTestSubscriberCampaign {
public TestCreateCampaign(String label, String apiKey, String userKey,
int customerId) {
super(label, apiKey, userKey, customerId);
}
#Before
public void setUp() throws Exception {
super.setUp();
}
#After
public void tearDown() throws Exception {
super.tearDown();
}
#Parameters
public static Collection<Object[]> generatedData() {
return DataProvider.generatedCorrectSubscriberData();
}
#Test
public void testCreateEmailCampaignBothTriggered() {
// TEST
}
#Test
public void testCreateTextCampaignTriggered() {
// TEST
}
#Test
public void testCreateTextCampaignTest() {
// TEST
}
// Other Tests
}
This depends on how you want to set up your classes, but you can use a ClassRule for this. This does the same job as a TestRule, but it runs once for each class, rather than each test. This can be combined with Parameterized and TestRule, such as:
#RunWith(Parameterized.class)
public class TestCreateCampaign {
#ClassRule
public static ExternalResource beforeAfterClass = new ExternalResource() {
#Override
protected void before() throws Throwable {
System.out.println("before each class");
}
#Override
protected void after() {
System.out.println("after each class");
}
};
#Rule
public ExternalResource beforeAfter = new ExternalResource() {
#Override
protected void before() throws Throwable {
System.out.println("before each test");
}
#Override
protected void after() {
System.out.println("after each test");
}
};
#Parameters(name = "{index}: fib({0})={1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] { { 3, 0 }, { 4, 1 } });
}
private int fInput;
private int fExpected;
public TestCreateCampaign(int input, int expected) {
fInput = input;
fExpected = expected;
}
#Test
public void test1() {
System.out.println("test1 fInput=" + fInput);
}
}
This produces the following output:
before each class
before each test
test1 3
after each test
before each test
test1 4
after each test
after each class
This seems to be what you're looking for. To cut down on the amount of duplication, you can of course define beforeAfterClass and beforeAfter in a separate java class.
These are available in JUnit 4.9+.
What about calling your setup method from the constructor of your parameterized test class?
Edit:
OK, do I don't know of anything that does this automatically, but I think you could code up a Rule to do it. You could either implement a Rule from scratch of extend ExternalResource. Here is what I think it would do.
The constructor would take an instance of the test class and an ExternalResource instance.
In the constructor it would find the list of methods that contain the #Test annotation a get a count. It would set an iteration count to 0.
In the before method it would increment the iteration count and if it is 1 after increment (or 0 before) it would invoke the before method on the passed ExternalResource.
In the after method it would check to see if the iteration count was equal to the number of tests and if so call the after method on the passed ExternalResource.
You might need to use a different callback class / interface and ExternalResource since the before and after methods are protected. If you really wanted to be cool, you would define your own BeforeParameters and AfterParameter annotations in your rule and it would look for those methods in the passed instance.
If you develop this please post it or submit it to JUnit for inclusion.
Here is what I came up with, not as nice as I would like:
#RunWith(Parameterized.class)
public class TestExample {
private interface BeforeAfter {
void before();
void after();
}
public static class Resource extends ExternalResource {
private final int count;
private final BeforeAfter ba;
private int iteration = 0;
Resource(Object instance, BeforeAfter ba) {
int localCount = 0;
for (Method method : instance.getClass().getMethods()) {
if (method.getAnnotation(Test.class) != null) {
localCount++;
}
}
this.count = localCount;
this.ba = ba;
}
#Override
protected void before() throws Throwable {
if (iteration == 0) {
ba.before();
}
iteration++;
}
#Override
protected void after() {
if (iteration == count) {
ba.after();
iteration = 0;
}
}
}
#Parameters
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][] { { 3, 0 }, { 4, 1 } });
}
#Rule
public static Resource resource = new Resource(new TestExample(0, 0), new BeforeAfter() {
#Override
public void before() {
System.out.println("setup");
}
#Override
public void after() {
System.out.println("cleanup");
}
});
private int fInput;
private int fExpected;
public TestExample(int input, int expected) {
// System.out.println("Constructor invoked" + fInput);
fInput = input;
fExpected = expected;
}
#Test
public void test1() {
System.out.println("test1 fInput=" + fInput);
}
#Test
public void test2() {
System.out.println("test2 fInput=" + fInput);
}
}
Resulted in:
setup
test1 fInput=3
test2 fInput=3
cleanup
setup
test1 fInput=4
test2 fInput=4
cleanup
See How to load DBUnit test data once per case with Spring Test for a way of initialising your test data only once per test run.

Using final object in anonymous inner class results in null

I have a method that contains the following code:
public void myMethod(){
final MyDto expectedtDto = new MyDto();
MyRepository reposWithMock = new MyRepository(){
protected MyDao createDao(){
return new MyDao() {
public MyDto someMethod(){
return expectedtDto;
}
};
}
};
reposWithMock.doSomethingWithDao();
}
MyRepository.createDao() is called from the constructor of MyRepository.
MyDao.someMethod() is called from MyRepository.doSomethingWithDao().
However, the MyDao().someMethod() returns null instead of the expectedDto
Any idea why this is?
For clarification, some real working code:
package nl.tests;
public class TestAnon {
static class MyDao {
private int value;
public MyDao(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
static class Repository {
private MyDao dao;
public Repository() {
dao = createDao();
}
protected MyDao createDao(){
return new MyDao( 4 );
}
public MyDao getDao(){
return dao;
}
}
public static void main(String[] args) {
final MyDao testDao = new MyDao(8);
Repository repos = new Repository() {
protected MyDao createDao() {
if ( testDao == null ) {
System.out.println( "Error ");
return new MyDao(0);
}
return testDao;
}
};
System.out.println( "Dao :" + repos.getDao().getValue() );
}
}
This results in :
Error
Dao :0
Some additional information: I currently (have to) work with java 1.4.
My development environment is Rational Application Developer 7.
Addendum, to the given (and accepted answer). For the below code I've made the createDao() method public :
public static void main(final String[] args) {
final MyDao testDao = new MyDao(8);
Repository repos = new Repository() {
public MyDao createDao() {
if ( testDao == null ) {
System.out.println( "Error ");
return new MyDao(0);
}
return testDao;
}
};
System.out.println( "Dao :" + repos.getDao().getValue() );
System.out.println( "Dao :" + repos.createDao().getValue() );
}
Returns:
Error
Dao :0
Dao :8
It fails in Java 1.4 because the field containing the local variable is not yet initialized when the super constructor for Repository is executed.
It works in Java 1.5 and later, because then the field is initialized before the super constructor is called.
In general it is bad style to call methods which may be overridden in subclasses in a constructor, because it leads to this kind of problems.
According to what you provided a quick test outputs MyDto#190d11 or similar. So I bet you left out some important code which is responsible for some variable name hiding.
Test.java
public class Test {
public static void main(String args[]) {
new Test().myMethod();
}
public void myMethod() {
final MyDto expectedtDto = new MyDto();
MyRepository reposWithMock = new MyRepository() {
#Override
protected MyDao createDao() {
return new MyDao() {
#Override
public MyDto someMethod(){
return expectedtDto;
}
};
}
};
reposWithMock.doSomethingWithDao();
}
}
MyDto.java
public class MyDto {}
MyRepository.java
public abstract class MyRepository {
protected abstract MyDao createDao();
public void doSomethingWithDao() {
System.out.println(createDao().someMethod());
}
}
MyDao.java
public abstract class MyDao {
public abstract MyDto someMethod();
}
Make sure you actually override the method you think you do. Your IDE or #Override should help.
Is MyDto a child of MyDao?
Your return a MyDto when the method indicates you return a MyDao.
Maybe that is a piece of the problem.
A second solution could be:
Put the expectedtDto in the inner-class instead of the method.
Martijn
Your code works for me. The only way I could see that expectedDto could be null within the anonymous inner class is if you're referencing it on another thread without proper synchronization.
The test-case you described works fine for me.
You should provide minimal but complete standalone test-case that illustrates the problem to get help.

Categories

Resources