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.
Related
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();
The Javadoc gives this example for the matches method:
assertThat(player).matches(p -> p.isRookie());
And indeed, when I define a dummy class Player, the above statement compiles ok. However, when I define a class that derives from Exception, then the following doesn't compile:
public class MyCustomException extends Exception {
public boolean isMyCustomFieldSet() { return true; }
}
...
MyCustomException myCustomException = new MyCustomExcpetion();
assertThat(myCustomException).matches(e -> e.isMyCustomFieldSet());
I can make it compile by using a cast:
assertThat(myCustomException).matches(e -> ((MyCustomException)e).isMyCustomFieldSet());
but that cast looks "ugly" and a bit of a hack to work around some sort of deficiency. Can I make it compile in a "nicer" way, i.e. without using a cast?
The issue is in Assertions, it declares AbstractThrowableAssert<?, ? extends Throwable> assertThat(Throwable t) instead of <T> AbstractThrowableAssert<?, T extends Throwable> assertThat(T t)
But unfortunately this can not be done because of the following existing method that clashes with it: public static <T> ObjectAssert<T> assertThat(T actual).
Casting is a solution, I agree it is not super elegant.
What I would do in that case is simply:
assertThat(myCustomException.isMyCustomFieldSet()).isTrue();
or to keep assertions on myCustomException directly:
assertThat(myCustomException).hasFieldOrPropertyWithValue("myCustomFieldSet", true)
.hasFieldOrPropertyWithValue("myOtherField", "foo");
The drawback here is accessing fields by name which is not refactoring friendly.
I don't think you'll be able to find a shorter way.
The issue is that
assertThat(new Player())
returns an ObjectAssert<Player>, with its matches signature being matches(Predicate<? super Player>).
However,
assertThat(new MyException())
actually calls a different method assertThat which returns an AbstractThrowableAssert<?, ? extends Throwable> with a matches(Predicate<? super Throwable>).
So that explains the issue, but I can't give you a better way to approach it.
I haven't checked whether an open issue exists against it, but it might be worth submitting one if it doesn't.
As my acknowledge, there is no way to using the method isMyCustomFieldSet directly. Because the assert lib using generic class and a generic class cannot extend the Throwable class directly or indirectly.
More info here
I've been trying to use Mockito and PowerMockito to test my code. I have something akin to the following class:
public class asdfClass{
public static String methodToMock(String item, String otheritem){
return "asdf";
}
public static String methodToMock(String item){
return "asdf";
}
}
For whatever reason, though, running the following:
PowerMockito.spy(asdfClass.class);
PowerMockito.when(asdfClass.methodToMock(Mockito.any())).thenReturn("asdfghj");
appears to compile correctly but running
PowerMockito.spy(asdfClass.class);
PowerMockito.when(asdfClass.methodToMock(Mockito.any(), Mockito.any())).thenReturn("asdfghj");
does not and spits out a "'void' type not allowed here" error on the Mockito.any()s.
Does anyone know what to do about this? The only other result I saw on stackoverflow suggested that the reader take a look at the documentation, though I don't think it said anything about multiple arguments in a private static method.
(In the end I'm hoping to mock a void result with a doNothing though I've boiled the issue I'm having down to the fact that all of my void methods take multiple arguments)
EDIT: Never mind, got it: Is it possible to use partial mocking for private static methods in PowerMock? (Comment 4 on the chosen answer). Curiously this didn't work before but that might've been a typo on my part for all I know)
As per Is it possible to use partial mocking for private static methods in PowerMock?, PowerMockito.doReturn(mockData).when(DataProvider.class, "readFile", param1, param2, ...) does the trick.
You mock void methods, so it can't return anything, so the thenReturn() statement should be omitted (for example instead of when(), use doNothing()).
in my test I have the following line:
when(client.runTask(anyString(), anyString(), isA(Iterable.class)).thenReturn(...)
isA(Iterable.class) produces warning that it needs unchecked conversion to conform to Iterable<Integer> . What is syntax for that?
isA(Iterable<Integer>.class)
isA((Iterable<Integer>)Iterable.class
do not work.
Any suggestions?
Mockito/Hamcrest and generic classes
Yes, this is a general problem with Mockito/Hamcrest. Generally using isA() with generic classes produces a warning.
There are predifined Mockito matchers for the most common generic classes: anyList(), anyMap(), anySet() and anyCollection().
Suggestions:
anyIterable() in Mockito 2.1.0
Mockito 2.1.0 added a new anyIterable() method for matching Iterables:
when(client.runTask(anyString(), anyString(), anyIterable()).thenReturn(...)
Ignore in Eclipse
If you just want to get rid of the warning in Eclipse. Option exists since Eclipse Indigo:
Window > Preferences > Java > Compiler > Errors/Warnings > Generic
types > Ignore unavoidable generic type problems
Quick Fix with #SuppressWarnings
I suggest you do this if you have the problem only once. I personally don't remember ever needing an isA(Iterable.class).
As Daniel Pryden says, you can limit the #SuppressWarnings to a local variable or a helper method.
Use a generic isA() matcher with TypeToken
This solves the problem for good. But it has two disadvantages:
The syntax is not too pretty and might confuse some people.
You have an additional dependency on the library providing the TypeToken class. Here I used the TypeToken class from Guava. There's also a TypeToken class in Gson and a GenericType in JAX-RS.
Using the generic matcher:
import static com.arendvr.matchers.InstanceOfGeneric.isA;
import static org.mockito.ArgumentMatchers.argThat;
// ...
when(client.runTask(anyString(), anyString(), argThat(isA(new TypeToken<Iterable<Integer>>() {}))))
.thenReturn(...);
Generic matcher class:
package com.arendvr.matchers;
import com.google.common.reflect.TypeToken;
import org.mockito.ArgumentMatcher;
public class InstanceOfGeneric<T> implements ArgumentMatcher<T> {
private final TypeToken<T> typeToken;
private InstanceOfGeneric(TypeToken<T> typeToken) {
this.typeToken = typeToken;
}
public static <T> InstanceOfGeneric<T> isA(TypeToken<T> typeToken) {
return new InstanceOfGeneric<>(typeToken);
}
#Override
public boolean matches(Object item) {
return item != null && typeToken.getRawType().isAssignableFrom(item.getClass());
}
}
Here's what I do:
// Cast from Class<Iterable> to Class<Iterable<Integer>> via the raw type.
// This is provably safe due to erasure, but will generate an unchecked warning
// nonetheless, which we suppress.
#SuppressWarnings("unchecked")
Class<Iterable<Integer>> klass
= (Class<Iterable<Integer>>) (Class) Iterable.class;
// later
isA(klass) // <- now this is typesafe
You can add #SuppressWarnings("unchecked") above the statement. No other way but if it bothers you, you can move the cast to a helper method.
There is no way to do this. To simplify, you can't initialize this variable without warning :
Class<Iterable<Integer>> iterableIntegerClass = ?
One solution might be to use the pseudo-typedef antipattern,
,you create and use an IntegerIterable interface
interface IntegerIterable extends Iterable<Integer> {}
then
isA(IntegerIterable.class)
will no more produce warning. But you will have to extend the class implementing Iterable to let them implements IntegerIterable :) For example :
public class IntegerArrayList extends ArrayList<Integer> implements IntegerIterable {}
Mmm tasty...
So, i will sugest you to consider to just paper over the cracks by adding to your method :
#SuppressWarnings("unchecked")
I have an interface Producer<T> and a concrete FooProducer that implements Producer<Foo>. Binding this in guice looks ugly as sin:
bind(new TypeLiteral<Producer<Foo>>() {}).to(FooProducer.class);
I have lots of these such bindings. I have tried the following:
static <T> TypeLiteral<Producer<T>> producer() {
return new TypeLiteral<Producer<T>>(){};
}
With calls made in this way:
bind(ContainingClass.<Foo>producer()).to(FooProducer.class);
But it gives an error along the lines of Producer<T> is not specific enough....
Am I going about this in the wrong way?
Instead of
bind(new TypeLiteral<Producer<Foo>>() {}).to(FooProducer.class);
try a convenience method like
static <T> Key<Producer<T>> producerOf(Class<T> type) {
return (Key<Producer<T>>)Key.get(Types.newParameterizedType(Producer.class,type));
}
and then in your module
bind(producerOf(Foo.class)).to(FooProducer.class);
That unchecked cast should be safe. Key is com.google.inject.Key and Types is com.google.inject.util.Types.
good luck
You can save 8 characters by typing new Key<Producer<Foo>>(){} rather than new TypeLiteral<Producer<Foo>>(){}. Or by using the equivalent #Provides method:
#Provides
public Producer<Foo> provideFooProducer(FooProducer fooProducer) {
return fooProducer;
}
I believe that due to how TypeLiterals work, you have to actually write new TypeLiteral<Producer<Foo>>(){} or the necessary type information will not be available. They utilize the fact that a class that has fully specified its generic types can have information on those types retrieved. When you write new TypeLiteral<Producer<T>>(){}, you aren't specifying what T is, so that information isn't available.
It's subjective, but I don't think creating a type literal looks too ugly, considering what it does.
As an aside, I don't know what your Producer interface does, but if it is just used for producing instances of T (with a method that takes no arguments), you could use Guice's Provider interface instead. Then you just have to do:
bind(Foo.class).toProvider(FooProvider.class);
And you can inject a Foo or a Provider<Foo> anywhere.