Mockito Answers: Capture any exceptions
This commit is contained in:
committed by
Artem Bilan
parent
e37e9aac28
commit
2874cd24c8
1
.gitignore
vendored
1
.gitignore
vendored
@@ -19,3 +19,4 @@ erl_crash.dump
|
||||
nohup.out
|
||||
src/ant/.ant-targets-upload-dist.xml
|
||||
target
|
||||
.sts4-cache
|
||||
|
||||
@@ -16,12 +16,17 @@
|
||||
|
||||
package org.springframework.amqp.rabbit.test.mockito;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
/**
|
||||
* An Answer to optionally call the real method and allow returning a
|
||||
* custom result.
|
||||
* An {@link Answer} to optionally call the real method and allow returning a
|
||||
* custom result. Captures any exceptions thrown.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 1.6
|
||||
@@ -33,6 +38,8 @@ public class LambdaAnswer<T> implements Answer<T> {
|
||||
|
||||
private final ValueToReturn<T> callback;
|
||||
|
||||
private final Set<Exception> exceptions = Collections.synchronizedSet(new LinkedHashSet<>());
|
||||
|
||||
public LambdaAnswer(boolean callRealMethod, ValueToReturn<T> callback) {
|
||||
this.callRealMethod = callRealMethod;
|
||||
this.callback = callback;
|
||||
@@ -42,12 +49,28 @@ public class LambdaAnswer<T> implements Answer<T> {
|
||||
@Override
|
||||
public T answer(InvocationOnMock invocation) throws Throwable {
|
||||
T result = null;
|
||||
if (this.callRealMethod) {
|
||||
result = (T) invocation.callRealMethod();
|
||||
try {
|
||||
if (this.callRealMethod) {
|
||||
result = (T) invocation.callRealMethod();
|
||||
}
|
||||
return this.callback.apply(invocation, result);
|
||||
}
|
||||
catch (Exception e) {
|
||||
this.exceptions.add(e);
|
||||
throw e;
|
||||
}
|
||||
return this.callback.apply(invocation, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the exceptions thrown, if any.
|
||||
* @return the exceptions.
|
||||
* @since 2.2.3
|
||||
*/
|
||||
public Collection<Exception> getExceptions() {
|
||||
return Collections.unmodifiableCollection(this.exceptions);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ValueToReturn<T> {
|
||||
|
||||
T apply(InvocationOnMock invocation, T result);
|
||||
|
||||
@@ -16,14 +16,20 @@
|
||||
|
||||
package org.springframework.amqp.rabbit.test.mockito;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* An Answer for void returning methods that calls the real method and
|
||||
* counts down a latch.
|
||||
* An {@link Answer} for void returning methods that calls the real method and counts down
|
||||
* a latch. Captures any exceptions thrown.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 1.6
|
||||
@@ -33,6 +39,8 @@ public class LatchCountDownAndCallRealMethodAnswer implements Answer<Void> {
|
||||
|
||||
private final CountDownLatch latch;
|
||||
|
||||
private final Set<Exception> exceptions = Collections.synchronizedSet(new LinkedHashSet<>());
|
||||
|
||||
/**
|
||||
* @param count to set in a {@link CountDownLatch}.
|
||||
*/
|
||||
@@ -42,8 +50,16 @@ public class LatchCountDownAndCallRealMethodAnswer implements Answer<Void> {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
invocation.callRealMethod();
|
||||
this.latch.countDown();
|
||||
try {
|
||||
invocation.callRealMethod();
|
||||
}
|
||||
catch (Exception e) {
|
||||
this.exceptions.add(e);
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
this.latch.countDown();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -52,4 +68,14 @@ public class LatchCountDownAndCallRealMethodAnswer implements Answer<Void> {
|
||||
return latch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the exceptions thrown.
|
||||
* @return the exceptions.
|
||||
* @since 2.2.3
|
||||
*/
|
||||
@Nullable
|
||||
public Collection<Exception> getExceptions() {
|
||||
return Collections.unmodifiableCollection(this.exceptions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -122,6 +123,10 @@ public class ExampleRabbitListenerSpyAndCaptureTest {
|
||||
assertThat((String) args[0]).isEqualTo("ex");
|
||||
assertThat((String) args[1]).isEqualTo(queue2.getName());
|
||||
assertThat(invocationData.getThrowable()).isNull();
|
||||
|
||||
Collection<Exception> exceptions = answer.getExceptions();
|
||||
assertThat(exceptions).hasSize(1);
|
||||
assertThat(exceptions.iterator().next()).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -177,10 +182,10 @@ public class ExampleRabbitListenerSpyAndCaptureTest {
|
||||
}
|
||||
|
||||
@RabbitListener(id = "bar", queues = "#{queue2.name}")
|
||||
public void foo(@Payload String foo, @Header("amqp_receivedRoutingKey") String rk) {
|
||||
public void foo(@Payload String foo, @SuppressWarnings("unused") @Header("amqp_receivedRoutingKey") String rk) {
|
||||
if (!failed && foo.equals("ex")) {
|
||||
failed = true;
|
||||
throw new RuntimeException(foo);
|
||||
throw new IllegalArgumentException(foo);
|
||||
}
|
||||
failed = false;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
package org.springframework.amqp.rabbit.test.mockito;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.willAnswer;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
@@ -40,6 +43,12 @@ public class AnswerTests {
|
||||
willAnswer(new LambdaAnswer<String>(false, (i, r) ->
|
||||
"" + i.getArguments()[0] + i.getArguments()[0])).given(foo).foo(anyString());
|
||||
assertThat(foo.foo("foo")).isEqualTo("foofoo");
|
||||
LambdaAnswer<String> answer = new LambdaAnswer<>(true, (inv, result) -> result);
|
||||
willAnswer(answer).given(foo).foo("fail");
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> foo.foo("fail"));
|
||||
Collection<Exception> exceptions = answer.getExceptions();
|
||||
assertThat(exceptions).hasSize(1);
|
||||
assertThat(exceptions.iterator().next()).isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
private static class Foo {
|
||||
@@ -49,6 +58,9 @@ public class AnswerTests {
|
||||
}
|
||||
|
||||
public String foo(String foo) {
|
||||
if (foo.equals("fail")) {
|
||||
throw new IllegalArgumentException("fail");
|
||||
}
|
||||
return foo.toUpperCase();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,19 +73,9 @@ assertEquals("thingthing", thing.thing("thing"));
|
||||
----
|
||||
====
|
||||
|
||||
The following example shows how to test the `Thing` POJO with Java 7 or earlier:
|
||||
Starting with version 2.2.3, the answers capture any exceptions thrown by the method under test.
|
||||
Use `answer.getExceptions()` to get a reference to them.
|
||||
|
||||
====
|
||||
[source, java]
|
||||
----
|
||||
doAnswer(new LambdaAnswer<String>(true, new ValueToReturn<String>() {
|
||||
@Override
|
||||
public String apply(InvocationOnMock i, String r) {
|
||||
return r + r;
|
||||
}
|
||||
})).when(thing).thing(anyString());
|
||||
----
|
||||
====
|
||||
|
||||
[[test-harness]]
|
||||
==== `@RabbitListenerTest` and `RabbitListenerTestHarness`
|
||||
|
||||
Reference in New Issue
Block a user