Mockito method parameter matcher with generic in java - java

My actual method signature is:
public List<T> readFileToMemory(FooFile fooFile, **Class<T> entityClass**) { }
and I am trying to mock this as:
when(mockObject.readFileToMemory(any(FooFile.class),
Matchers.any(Class<Bar>)).thenReturn(new ArrayList<Bar>())
but second argument doesn't compile. How to fix it?
I referred to the following answers but still no luck.
Mockito: List Matchers with generics
Mockito: Verifying with generic parameters

Oh i fixed it as:
when(mockObject.readFileToMemory(any(FooFile.class),
Matchers.<Class<Bar>>any())).thenReturn(new ArrayList<Bar>())

You could also get it working with:
when(mockObject.readFileToMemory(any(FooFile.class), eq(Bar.class)))
.thenReturn(new ArrayList<Bar>());

Related

Return class from method in mocked method. Mockito

I have class TaskType. It has method
public Class<? extends TaskParameters> getTypeParameters() {
return typeParameters;
}
next i want to mock this class and mock this method:
final TaskType TEST_PARAMETERS = Mockito.mock(TaskType.class);
when(TEST_PARAMETERS.getTypeParameters()).thenReturn(ScheduledParameters.class);
Mockito.doReturn(4).when(TEST_PARAMETERS).ordinal();
but i got problem:
error: no suitable method found for thenReturn(java.lang.Class<com.ucp.shard.bulkops.service.executor.ScheduleExecutorTest.ScheduledParameters>)
when(TEST_PARAMETERS.getTypeParameters()).thenReturn(ScheduledParameters.class);
Help, how can i mock this method?
Your question is missing a lot of information, it would be nice if you could update it. For example, you could share the code for TaskType.
First of all, it seems that TaskType is an enum as you are trying to call ordinal(), right? If it's the case, you need to remember that enums are final and cannot be mocked by Mockito by default (please read here for more information). If it's not an enum you can ignore it. :)
Regarding the problem mocking getTypeParameters(), you cannot do it directly due to type erasure (more information here). However, you can solve it using Mockito Answer:
final TaskType TEST_PARAMETERS = Mockito.mock(TaskType.class);
final Answer<Class<ScheduledParameters>> answer = invocation -> ScheduledParameters.class;
when(TEST_PARAMETERS.getTypeParameters())
.thenAnswer(answer);
Mockito.doReturn(4).when(TEST_PARAMETERS).ordinal();

Mockito; Mock a method that calls a lambda, and verify another mock called by that lambda

My question, which was similar to this:
Using mockito; is it possible to mock a method that takes a lambda as a parameter and assert variables captured by the lambda?
But different enough that I still had take a while to figure it out was:
How do I verify that a method called by a mock that was used inside a lambda that was passed to a method of another mock object?
This may seem convoluted, but it happens a lot with Java 8 libraries like JDBI, for example, you have a JDBI object:
JDBI MyDBConnection
That you should mock. And then that is used with the withHandle method to pass a lambda implementing the HandleCallback<R,X> type:
//code I'm testing. I implement the lambda, and want to verify it
//calls the correct method in dao provided by JDBI.
MyDBConnection.withHandle(
(handle) -> { ... handle.attach(SomeDao.class).findSomethingInDB(args) .. }
Which is the recommended way to do this.
So I want to verify that findSomethingInDB(eq(args)) is called.
Like I said this was similar, but different enough, that, I at least, will find this answer valuable at some future point, when I forget how to do this. So the original 3rd party library method that invokes my lambda is processed similar to the answer given in the question referenced above, but with some tweaks:
when(JDBIMock.withHandle(any())).then(
//Answer<Void> lambda
invocationOnMock -> {
Object[] args = invocationOnMock.getArguments();
assertEquals(1, args.length);
//the interface def for the callback passed to JDBI
HandleCallback lambda = (HandleCallback) args[0];
when(mockHandle.attach(SomeDao.class)).thenReturn(mockDao);
//this actually invokes my lambda, which implements the JDBI interface, with a mock argument
lambda.withHandle(mockHandle);
//bingo!
verify(mockDao).findSomethingInDB(eq(args));
}
)
See the question, it should be answered sufficiently above ;)
I am trying to do something very similar with verifying the arguments passed to another mock from withHandle on a mock JDBI call in a test.
The answer you give in the question pointed me in the right direction but gives me the error message:
The method then(Answer<?>) in the type OngoingStubbing<Object> is not applicable for the arguments ((<no type> invocationOnMock) -> {})
Instead I had to use a new org.mockito.stubbing.Answer passed to the then, similar to in the other question you linked to.
In your example this would be something like:
when(JDBIMock.withHandle(any())).then(
//Answer<Void> lambda
new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
assertEquals(1, args.length);
//the interface def for the callback passed to JDBI
HandleCallback lambda = (HandleCallback) args[0];
when(mockHandle.attach(SomeDao.class)).thenReturn(mockDao);
//this actually invokes my lambda, which implements the JDBI interface, with a mock argument
lambda.withHandle(mockHandle);
//bingo!
verify(mockDao).findSomethingInDB(eq(args));
return null; // to match the Void type
}
}
)
In my case I was expecting a result list from withHandle so I had to change the Answer type, and return type of answer to match and return a dummy list instead of Void. (The actual results returned didn't matter in this test, only that the expected arguments were passed to my subsequent mock object).
I also moved the verify call outside of the Answer into the main body of my test so it was clearer this was the expectation of the test, not part of the mocking setup.

Mockito, mock class and real call void Methods

as the title suggests, the problem is this: I have the mock of AdesioneMerger and I have to call the real merge method. merge is a void method.
This is wrong:
adesioneMerger = Mockito.spy(AdesioneMerger.class);
Mockito.when(adesioneMerger.merge(
Matchers.any(AdesioneBean.class),
Matchers.any(Adesione.class),
Matchers.any(ServiceResultBean.class))
).ThenCallRealMethod();
what's the error?
For void methods, use the alternative API:
Mockito.doCallRealMethod()
.when(adesioneMerger).merge(
Matchers.any(AdesioneBean.class),
Matchers.any(Adesione.class),
Matchers.any(ServiceResultBean.class));
The problem is that Mockito.when() requires an argument (and there are no void-typed arguments in Java). The alternative API works around this by calling when() on the mock type and the actual method to mock is called on the return value of when(...).
See also this answer: How to make mock to void methods with mockito
try this way:
doCallRealMethod().when(adesioneMerger).merge(
Matchers.any(AdesioneBean.class),
Matchers.any(Adesione.class),
Matchers.any(ServiceResultBean.class);

EasyMock and generic params

I'm trying to get to grips with EasyMock to mock some calls to Jersey client APIs...
I'm trying to mock a call to the following call Builder API:
<T> T post(Entity<?> entity, Class<T> responseType);
doing the following:
EasyMock.expect(mockInvocationBuilder.post(Entity.json(request), Response.class)).andReturn(mockResponse).anyTimes();
this is giving me the following error:
java.lang.AssertionError:
Unexpected method call Builder.post(Entity{entity=com.ibm.apin.apim.request.CreateOrgRequest#936a7073, variant=Variant[mediaType=application/json, language=null, encoding=null], annotations=[]}, class javax.ws.rs.core.Response):
Can anyone see what I'm doing wrong here and how I can mock this correctly?
See EasyMock User Guide:
To match an actual method call on the Mock Object with an expectation, Object arguments are by default compared with equals().
You have to override equals(), use a built-in argument matcher (like EasyMock#anyObject), write your own IArgumentMatcher or use a Capture.

Mockito: Verifying with generic parameters

With Mockito I can do the following:
verify(someService).process(any(Person.class));
But how do I write this if process takes a Collection<Person> instead? Can't figure out how to write it correctly. Just getting syntax errors...
Try:
verify(someService).process(ArgumentMatchers.<Collection<Person>>any());
Actually, IntelliJ automatically suggested this fix when I typed any()... Unfortunately you cannot use static import in this case.
Try :
verify(someService).process(anyCollectionOf(Person.class));
Since version 1.8 Mockito introduces
public static <T> Collection<T> anyCollectionOf(Class<T> clazz);
if you use a own method, you can even use static import:
private Collection<Person> anyPersonCollection() {
return any();
}
Then you can use
verify(someService).process(anyPersonCollection());
As an alternative to the accepted answer you can try:
verify(someService).process(Mockito.<SomeGenericClass<Person>>any());
Where I used org.mockito.Mockito instead of Matchers.
You can't express this because of type erasure. Even if you could express it in code, Mockito had no chance to check it at runtime. You could create an interface like
interface PersonCollection extends Collection<Person> { /* nothing */ }
instead and use this throughout your code.
Edit: I was wrong, Mockito has anyCollectionOf(..) which is what you want.

Categories

Resources