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");
}
Related
I'm fairly new to Mockito, and I've been looking for a way to verify that if I call the filter() method with the right string, that the foo method will get called once.
public class A
{
private final Config _config;
public A(Config config) { _config = config; }
public void filter(String str)
{
if(str.startsWith("a"))
{
if(str.contains("z"))
{
foo(config.getName());
}
}
}
private void foo(String bar)
{
(...)
}
}
Here is my current code:
#Test
public void testOne()
{
Config config = new Config(configFile);
A a = Mockito.spy(new A(config));
a.filter("abcz");
verify(a, times(1)).foo(someString);
}
Try to be more generic while such a test. If you don't need to specify what exactly argument should by passed then just use any():
import static org.mockito.ArgumentMatchers.any;
verify(a).foo(any(String.class));
For JUnit testing I want to mock an overloaded method. There is no need to implement several methods in the mockbuilder though.
I want to do something like this:
Mockito.when(mock.getSomeInfo(Mockito.any(ArgumentType1.class) OR Mockito.any(ArgumentType2.class), Mockito.any(ArgumentType3.class))).then(new Answer<AnswerType>() {..}
I know it doesn't work with the OR statement, but is there another way to do this in Mockito?
As mentioned on the mockito github:
It looks like this has to do with calling when the second time. I couldn't find what was going on, but the second when doesn't attempt to add the mock logic, it just calls the method. Replacing with doReturn().when() works.
doReturn(expected1).when(overloadedMethods).getString(any());
doReturn(expected2).when(overloadedMethods).getString(any(), any());
https://github.com/mockito/mockito/issues/1496#issuecomment-423310950 DavidTanner
You can do this with a custom matcher.
Warning: Be reasonable with using complicated argument matching, especially custom argument matchers, as it can make the test less readable. Sometimes it's better to implement equals() for arguments that are passed to mocks (Mockito naturally uses equals() for argument matching). This can make the test cleaner.
public class TypeOrMatcher extends ArgumentMatcher<Object> {
private final List<Class<?>> clazzes;
public TypeOrMatcher(Class<?>...clazzes) {
this.clazzes = new ArrayList<Class<?>>(clazzes);
}
public boolean matches(Object actual) {
if (actual == null) {
return false;
}
Class<?> actualClass = actual.getClass();
for (Class<?> clazz : clazzes) {
if (clazz.isAssignableFrom(actualClass) {
return true;
}
}
return false;
}
}
TypeOrMatcher isTypeOneOrTwo = new TypeOrMatcher(
ArgumentType1.class, ArgumentType2.class);
Some mockObj = mock(Some.class);
when(mockObj.someMethod(argThat(isTypeOneOrTwo), any(ArgumentType3.class))
.thenReturn(true);
You can pre-create the answer object you want to return and then return this answer.
class A {
public int test(final String s) {
return 0;
}
public int test(final int i) {
return 0;
}
}
And in the test method:
public void testAtest() {
final A a = Mockito.mock(A.class);
final Answer<Integer> answer = new Answer<Integer>() {
#Override
public Integer answer(final InvocationOnMock invocation) throws Throwable {
return 0;
}
};
Mockito.when(a.test(Matchers.anyInt())).then(answer);
Mockito.when(a.test(Matchers.anyString())).then(answer);
}
For an example I have a service class that will be called from testing method:
public interface AService{
public ReturnObject addNewItem(String param1, String param2);
public ReturnObject addNewItem(String param1, String param2, boolean isOk);
}
Have a method in MainServiceImpl class will call an overloaded method like below:
#Service("mainService")
public class MainServiceImpl implements MainService {
#Autowired
private AService aService;
public ReturnObject saveItem(String itemName, String itemCode){
return aService.addNewItem(itemName, itemCode);
}
}
So when we have to write unit test for saveItem the method which already calls to overloaded method as addNewItem, if you had used normal way to create a mock then you answer will not return what you want in answer object return.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ })
public class ItemTest{
#Test
public void testSaveItem() throws Exception {
//create a real object of MainServiceImpl
MainServiceImpl mainService = new MainServiceImpl();
//create a normal way for a mocking object
AService aService = Mockito.mock(AService.class);
// Add mock object to MainServiceImpl instance
ReflectionTestUtils.setField(mainService, "aService", aService);
//Mock when aService call to addNewItem() method
PowerMockito.when(aService , "addNewItem", Mockito.anyString(), Mockito.anyString()).then(new Answer<ReturnObject>() {
#Override
public ReturnObject answer(InvocationOnMock invocation) throws Throwable {
return new ReturnObject("saveOK");
}
});
ReturnObject returnObj = mainService.saveItem("Book", "Code123");
Assert.assertNotNull(returnObj);
}
}
Try to replace testSaveItem above by with testSaveItem below then success:
#Test
public void testSaveItem() throws Exception {
//create a real object of MainServiceImpl
MainServiceImpl mainService = new MainServiceImpl();
//create a special way for a mocking object by add
//the answer at create the mock object
final Answer<ReturnObject> answer = new Answer<ReturnObject>() {
#Override
public ReturnObjectanswer(final InvocationOnMock invocation) throws Throwable {
return new ReturnObject("saveOK");
}
};
AService aService = Mockito.mock(AService.class, answer);
// Add mock object to MainServiceImpl instance
ReflectionTestUtils.setField(mainService, "aService", aService);
//Mock when aService call to addNewItem() method
PowerMockito.when(aService , "addNewItem", Mockito.anyString(), Mockito.anyString()).then(new Answer<ReturnObject>() {
#Override
public ReturnObject answer(InvocationOnMock invocation) throws Throwable {
return new ReturnObject("saveOK");
}
});
ReturnObject returnObj = mainService.saveItem("Book", "Code123");
Assert.assertNotNull(returnObj);
}
Does somebody know how to change the return value of the method in the final class.
I'm trying to test the ToBeTested class and I want to get true as the result.
I tried to use Powermockito but didn't find a solution.
public final class ToBeChanged {
public static boolean changeMyBehaviour() {
return false;
}
}
public class ToBeTested {
public boolean doSomething () {
if (ToBeChanged.changeMyBehaviour)
return false;
else
return true;
}
}
I do not want to declare the ToBeChanged class as a field in the ToBeTested class.
So there is no way to change the implemented classes itself.
With the JMockit tool, the test would be like this:
#Test
public void doSomething(#Mocked ToBeChanged mock)
{
new NonStrictExpectations() {{ ToBeChanged.changeMyBehaviour(); result = true; }};
boolean res = new ToBeTested().doSomething();
assertTrue(res);
}
Hide the static dependency behind an interface. Mock the interface.
Since you don't want to have a field on your class, simply pass the interface as a method parameter (alternatively get an instance through a factory, just don't use tight coupling)
public final class ToBeChanged {
public static boolean changeMyBehaviour() {
return false;
}
}
public interface MyInterface {
boolean changeMyBehaviour();
}
public class MyInterfaceImpl implements MyInterface {
#Override
public boolean changeMyBehaviour() {
return ToBeChanged.changeMyBehaviour();
}
}
class ToBeTested {
public boolean doSomething (MyInterface myInterface) {
return !myInterface.changeMyBehaviour();
}
}
class TheTest {
#Test
public void testSomething() {
MyInterface myMock = mock(MyInterface.class);
when(myMock.changeMyBehaviour()).thenReturn(true);
new ToBeTested().doSomething(myMock);
}
}
i have such java codes:
public class A {
public int get() {
// many codes
String s = new String();
//...
int n = 5;
return isEmpty(s) ? n : -1;
}
public boolean isEmpty(String s) {
return s.isEmpty();
}
}
now i want to just test get(), i don't want to test isEmpty() at the same, so i want to mock isEmpty(), just test a method, if it invokes another method of the class, can easymock mock the method?
A workable approach is to not mock A and do something like
public class TestableA extends A
{
#Override
public boolean isEmpty( String s )
{
// "mock" impl goes here, eg.:
return s;
}
}
and write your unit test in terms of TestableA instead. You can even create this in a #Before method:
public class UnitTest
{
private A a; // note: A, not TestableA!
#Before
public void setUp()
{
this.a = new A()
{
#Override
public boolean isEmpty( String s )
...
}
}
#Test
...
}
I want to change the object return from call to a constuctor
FROM
public class A {
public A(){
}
public String sayHello() {
return "hello";
}
public String foo() {
return "foo";
}
}
TO
public class AWrapped extends A {
private A wrapped;
public AWrapped() {
super();
}
public AWrapped(A pWrapped) {
wrapped=pWrapped;
}
public String foo() {
return wrapped.foo();
}
public String sayHello {
return "gday mate";
}
}
What i want to do is to change the object that is returned from a call
A a = new A();
a.sayHello() returns "gday mate"
a is an instaceof AWrapped
I understand that this would usually be done with a factory pattern but I dont have access to the code of A or the code that makes new A's. And there are 1000s of places that A can be created.
It seems that Aspectj might do the trick, but i dont know much about it, If AspectJ would do the trick how to I get around the infinite wrapping i need to know that its being consturcted from within and aspect so it doesnt wrapp it again.
Thanks for the help
Jon
If I understand you right you could do the following:
I've created three packages:
aspectj for the aspect and AWrapped.java
unknown for A.java (could also be Bytecode but then you have to use Load Time Weaving)
main to test A a = new A();
MyAspect to return the AWrapped object if a new() call is made on class A:
package aspectj;
import unknown.A;
#Aspect
public class MyAspect {
#Pointcut("call(unknown.A.new(..)) && !within(aspectj..*)")
public static void init(ProceedingJoinPoint pjp) {
}
#Around("init(pjp)")
public Object initAdvice(ProceedingJoinPoint pjp) throws Throwable{
Object ret = pjp.proceed();
return new AWrapped((A) ret);
}
}
For testing:
package main;
import unknown.A;
public class Main {
public static void main(String[] args) {
A a = new A();
System.out.println(a.sayHello());
}
}
This outputs:
gday mate