|
|
|
import java.util.LinkedList; |
|
import java.util.List; |
|
|
|
import org.mockito.ArgumentMatcher; |
|
import org.mockito.invocation.InvocationOnMock; |
|
import org.mockito.stubbing.Answer; |
|
|
|
import lombok.AllArgsConstructor; |
|
import lombok.Setter; |
|
import lombok.experimental.Accessors; |
|
|
|
/** |
|
* Helpers class to match multi calls to the same method. |
|
* @param <T> Argument type. |
|
* @param <R> Result type. |
|
*/ |
|
@Accessors(fluent = true) |
|
public class ArrayMatcherAnswer<T, R> implements Answer<R>, ArgumentMatcher<T> { |
|
|
|
@AllArgsConstructor |
|
private static class AnswerMock<T, R> { |
|
|
|
private final ArgumentMatcher<T> matcher; |
|
|
|
private final R result; |
|
} |
|
|
|
private final List<AnswerMock<T, R>> array = new LinkedList<>(); |
|
|
|
@Setter |
|
private R defaultResult; |
|
|
|
private AnswerMock<T, R> currentMock; |
|
|
|
/** |
|
* Add an argument matcher with the attached result. |
|
* @param matcher Argument matcher. |
|
* @param result Result to return. |
|
* @return this |
|
*/ |
|
public ArrayMatcherAnswer<T, R> add(final ArgumentMatcher<T> matcher, final R result) { |
|
this.array.add(new AnswerMock<>(matcher, result)); |
|
return this; |
|
} |
|
|
|
/** |
|
* Add an argument matcher with the default result. |
|
* @param matcher Argument matcher. |
|
* @return this |
|
*/ |
|
public ArrayMatcherAnswer<T, R> add(final ArgumentMatcher<T> matcher) { |
|
return this.add(matcher, this.defaultResult); |
|
} |
|
|
|
/** |
|
* Add an argument with the default result. |
|
* Use {@linkplain Object#equals(Object)} as {@linkplain ArgumentMatcher}. |
|
* @param object Argument |
|
* @return this |
|
*/ |
|
public ArrayMatcherAnswer<T, R> add(final T object) { |
|
return this.add(object, this.defaultResult); |
|
} |
|
|
|
/** |
|
* Add an argument with the given result. |
|
* Use {@linkplain Object#equals(Object)} as {@linkplain ArgumentMatcher}. |
|
* @param object Argument |
|
* @param result Result to return. |
|
* @return this. |
|
*/ |
|
public ArrayMatcherAnswer<T, R> add(final T object, final R result) { |
|
return this.add(object::equals, result); |
|
} |
|
|
|
@Override |
|
public R answer(final InvocationOnMock invocation) throws Throwable { |
|
return this.currentMock.result; |
|
} |
|
|
|
@Override |
|
public boolean matches(final T argument) { |
|
this.currentMock = this.array.stream() |
|
.filter(a -> a.matcher.matches(argument)) |
|
.findAny() |
|
.orElse(null); |
|
return this.currentMock != null && this.array.remove(this.currentMock); |
|
} |
|
|
|
} |