Null Pointer Error when Mocking JDBC Template execute method [duplicate] - spring-boot

I've been trying to get to mock a method with vararg parameters using Mockito:
interface A {
B b(int x, int y, C... c);
}
A a = mock(A.class);
B b = mock(B.class);
when(a.b(anyInt(), anyInt(), any(C[].class))).thenReturn(b);
assertEquals(b, a.b(1, 2));
This doesn't work, however if I do this instead:
when(a.b(anyInt(), anyInt())).thenReturn(b);
assertEquals(b, a.b(1, 2));
This works, despite that I have completely omitted the varargs argument when stubbing the method.
Any clues?

Mockito 1.8.1 introduced anyVararg() matcher:
when(a.b(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b);
Also see history for this: https://code.google.com/archive/p/mockito/issues/62
Edit new syntax after deprecation:
when(a.b(anyInt(), anyInt(), ArgumentMatchers.<String>any())).thenReturn(b);

A somewhat undocumented feature: If you want to develop a custom Matcher that matches vararg arguments you need to have it implement org.mockito.internal.matchers.VarargMatcher for it to work correctly. It's an empty marker interface, without which Mockito will not correctly compare arguments when invoking a method with varargs using your Matcher.
For example:
class MyVarargMatcher extends ArgumentMatcher<C[]> implements VarargMatcher {
#Override public boolean matches(Object varargArgument) {
return /* does it match? */ true;
}
}
when(a.b(anyInt(), anyInt(), argThat(new MyVarargMatcher()))).thenReturn(b);

Building on Eli Levine's answer here is a more generic solution:
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.mockito.ArgumentMatcher;
import org.mockito.internal.matchers.VarargMatcher;
import static org.mockito.Matchers.argThat;
public class VarArgMatcher<T> extends ArgumentMatcher<T[]> implements VarargMatcher {
public static <T> T[] varArgThat(Matcher<T[]> hamcrestMatcher) {
argThat(new VarArgMatcher(hamcrestMatcher));
return null;
}
private final Matcher<T[]> hamcrestMatcher;
private VarArgMatcher(Matcher<T[]> hamcrestMatcher) {
this.hamcrestMatcher = hamcrestMatcher;
}
#Override
public boolean matches(Object o) {
return hamcrestMatcher.matches(o);
}
#Override
public void describeTo(Description description) {
description.appendText("has varargs: ").appendDescriptionOf(hamcrestMatcher);
}
}
Then you can use it with hamcrest's array matchers thus:
verify(a).b(VarArgMatcher.varArgThat(
org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test")));
(Obviously static imports will render this more readable.)

I have been using the code in Peter Westmacott's answer however with Mockito 2.2.15 you can now do the following:
verify(a).method(100L, arg1, arg2, arg3)
where arg1, arg2, arg3 are varargs.

I had to use the any(Class type) method to match an array arg being passed as a varargs parameter.
ArgumentMatchers.any(Class type)
Code in the implementation is vararg aware.
reportMatcher(new InstanceOf.VarArgAware(
In my case where matching a String[] arg to a String... param the following worked:-
any(String.class)

Building on topchef's answer,
For 2.0.31-beta I had to use Mockito.anyVararg instead of Matchers.anyVararrg:
when(a.b(anyInt(), anyInt(), Mockito.<String>anyVararg())).thenReturn(b);

Adapting the answer from #topchef,
Mockito.when(a.b(Mockito.anyInt(), Mockito.anyInt(), Mockito.any())).thenReturn(b);
Per the java docs for Mockito 2.23.4, Mockito.any() "Matches anything, including nulls and varargs."

You can accomplish this by passing an ArgumentCaptor capture and then retrieving the varargs as a list using "getAllValues", see: https://stackoverflow.com/a/55621731/11342928

As the other answers make sense and make tests work obviously, I still recommend to test as if the method didn't take a vararg, but rather regular well-defined parameters instead. This helps in situations where overridden methods in connection with possible ambiguous parameters are in place, like an SLF4J-logger:
to test:
jobLogger.info("{} finished: {} tasks processed with {} failures, took {}", jobName, count, errors, duration);
This has a bunch of overrides and the important method being declared like so
Logger.info(String, Object...)
verification:
verify(loggerMock).info(anyString(), anyString(), anyInt(), anyInt(), anyString());
proof that the above works as errors is an integer and not a long, so the following wouldn't run:
verify(loggerMock).info(anyString(), anyString(), anyInt(), anyLong(), anyString());
So you can easily use when() instead of the verify()-stuff to set up the required return value.
And it probably shows more of the intent and is more readable. Captures can also be used here and they are much easier accessible this way.
Tested with Mockito 2.15

In my case the signature of the method that I want to capture its argument is:
public byte[] write(byte ... data) throws IOException;
In this case you should cast to byte array explicitly:
when(spi.write((byte[])anyVararg())).thenReturn(someValue);
I'm using mockito version 1.10.19

You can also loop over the arguments:
Object[] args = invocation.getArguments();
for( int argNo = 0; argNo < args.length; ++argNo) {
// ... do something with args[argNo]
}
for example check their types and cast them appropriately, add to a list or whatever.

Related

Mocking an extension function with Mockito

How can I test an extension function with Mockito? It doesn't seem to work nicely.
This is my extension function
fun <T> CrudRepository<T, String>.findOneById(id: String): T? {
val o = findById(id)
return if (o.isPresent) o.get() else null
}
And this is what I'm trying to test
#Test
fun getIslandById() {
//given
BDDMockito.given(islandRepository.findOneById("islandId1"))
.willReturn(IslandEntity(tileList, "1", "islandId1")) //findOneById is my extension function
//when
val island = islandService.getIslandById("islandId1")
//then
Assertions.assertThat(island?.id).isEqualTo("islandId1")
}
But the preceeding test throws the following error
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
IslandEntity cannot be returned by findById()
findById() should return Optional
Any ideas?
Instance extension functions can be mocked like this with a little help of mockito-kotlin:
data class Bar(thing: Int)
class Foo {
fun Bar.bla(anotherThing: Int): Int { ... }
}
val bar = Bar(thing = 1)
val foo = mock<Foo>()
with(foo) {
whenever(any<Bar>().bla(any()).doReturn(3)
}
verify(foo).apply {
bar.bla(anotherThing = 2)
}
As I said in a comment above, in the bytecode extension functions are nothing more than static functions which accept receiver as a first argument. Therefore you can't mock an extension function with a Mockito since it is not able to mock static functions.
What you can do, in case that findById(id) is implemented by Repository and not another extension function, is next:
Mock return value of findById(id) instead.
Take a look at the sample code below:
#Test
fun getIslandById() {
//given
BDDMockito.given(islandRepository.findById("islandId1"))
.willReturn(Optional.of(IslandEntity(tileList, "1", "islandId1"))) //mock findById function
//when
val island = islandService.getIslandById("islandId1")
//then
Assertions.assertThat(island?.id).isEqualTo("islandId1")
}
This way you are indirectly mocking your extension by providing it a mocked value that you want it to operate on.
Note: Error that you posted above says that your findById(id) should return an optional. So, wrap your return value of findById(id) function with an optional by calling Optional.of(result).

can i convert any lambda expression into method reference

I wonder if can i convert any lambda expression into method reference
for example:
if there is a lambda that execute method with 2 parameters (one of them is from outside)
.map( t -> removeFilesIfNessasary( externalObj, t ) )
can this also converted into method reference?
thanks
Well you could create a class, sort of like this:
class Remover {
private final Object externalObj;
public Remover(Object externalObj){
this.externalObj = externalObj;
}
public removeIf(int t){
removeFilesIfNessasary( externalObj, t);
}
}
and then declare this and use it:
Remover remover = new Remover(externalObj);
.map(remover::remove);
But seriously, this looks really weird; there has to be a compelling reason for you to do this (I can't think of one).

Combining functions and consumers with double-column notation

I often use the double-colon notation for brevity.
I am writing the following method that takes a short list of entities, validates them, and saves back to database.
#Override#Transactional
public void bulkValidate(Collection<Entity> transactions)
{
Consumer<Entity> validator = entityValidator::validate;
validator = validator.andThen(getDao()::update);
if (transactions != null)
transactions.forEach(validator);
}
I'd like to know if there is a shorthand syntax avoiding to instantiate the validator variable
Following syntax is invalid ("The target type of this expression must be a functional interface")
transactions.forEach((entityValidator::validate).andThen(getDao()::update));
You could do that, but you would need to cast explicitly...
transactions.forEach(((Consumer<Entity>)(entityValidator::validate))
.andThen(getDao()::update));
The thing is that a method reference like this entityValidator::validate does not have a type, it's a poly expression and it depends on the context.
You could also define a method to combine these Consumers:
#SafeVarargs
private static <T> Consumer<T> combine(Consumer<T>... consumers) {
return Arrays.stream(consumers).reduce(s -> {}, Consumer::andThen);
}
And use it:
transactions.forEach(combine(entityValidator::validate, getDao()::update))

Dropwizard deserializing generic list from JerseyClient

I wanted to implement a generic class to use for caching results from a REST API in a local MongoDB-instance. For this to work, I need to deserialize a collection I get from JerseyClient:
Response response = this.source.request().get();
List<T> list = response.readEntity( new GenericType<List<T>>() {} );
// ... do stuff with the list
Let's say I'm using this piece of code in a context of T relating to a class Foo. The really weird thing is, after the readEntity call, list is not a List<Foo>, instead is a List<LinkedHashMap>. How is that even possible, when I've clearly declared the Generic T to be Foo?
What do I have to do to get a proper List<T>, i.e. List<Foo> instead?
Note: If I remove the generic, and use
List<Foo> list = response.readEntity( new GenericType<List<Foo>>() {} );
directly instead, it works fine, but I really need that generic to be there!
Java's most popular excuse for Generics: Type Erasure
If you can pass your class type as Class<T> clazz, then you can use this:
GenericType<List<T>> genericType = new GenericType<>(new ParameterizedType() {
public Type[] getActualTypeArguments() {
return new Type[]{clazz};
}
public Type getRawType() {
return List.class;
}
public Type getOwnerType() {
return null;
}
});
response.readEntity(genericType);
You can use
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
import javax.ws.rs.core.GenericType;
GenericType<List<T>> genericType = new GenericType<>(
ParameterizedTypeImpl.make( List.class, new Type[]{classType}, null));

Spring SpEL chooses wrong method to invoke

I'm trying to evaluate the following SpEL expression (Spring-expression version 3.1.1):
T(com.google.common.collect.Lists).newArrayList(#iterable)
where #iterable is of type java.lang.Iterable.
Google Guava com.google.common.collect.Lists (version 14.0) does have a method newArrayList(Iterable) but for some reason SpEL chooses to invoke a different method: newArrayList(Object[])
I dived into the code and found the issue to be with org.springframework.expression.spel.support.ReflectiveMethodResolver implementation: it seems to be sensitive to the manner in which methods are sorted by the java.lang.Class::getMethods.
If 2 methods match the invocation (in the case one of the methods is varargs), the later method (in the order) will be invoked, instead of choosing the method that isn't varargs (which is more specific).
It seems like JDK doesn't guarantee the order the methods are sorted: different runs show different order.
Is there a way to overcome this issue?
You can use the collection projections of Spring EL to select all from iterable and convert it to list:
"#iterable.?[true]"
A simple example to test:
Iterable<Integer> it = () -> new Iterator<Integer>() {
private int[] a = new int[]{1, 2, 3};
private int index = 0;
#Override
public boolean hasNext() {
return index < a.length;
}
#Override
public Integer next() {
return a[index++];
}
};
Tmp tmp = new Tmp();
tmp.setO(it);
StandardEvaluationContext context = new StandardEvaluationContext(tmp);
ArrayList<Integer> list = parser.parseExpression("o.?[true]").getValue(context,
ArrayList.class);

Resources