Repository: mockito/mockito
Issue: Improve usability of arity Answers with regards to checked exceptions
Labels: bug

Recently introduced Answer1 style answers don't declare Throwable. They should! Otherwise the user is forced to add boilerplate code to AnswerX implementations, whenever they use methods that declare checked exceptions. Plus, AnswerX should behave exactly as good old Answer interface!

Reported via the [mailing-list](https://groups.google.com/d/msgid/mockito/82d08ba9-5536-495e-90db-78c1062b6400%40googlegroups.com)


Issue comments:
Given how Answer is supposed to be used it is a safe change to do. Plus, it is marked as @Incubating :)


Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/stubbing/Answer1.java b/src/main/java/org/mockito/stubbing/Answer1.java
index 23bf06c66b..dcc3ce9083 100644
--- a/src/main/java/org/mockito/stubbing/Answer1.java
+++ b/src/main/java/org/mockito/stubbing/Answer1.java
@@ -3,13 +3,36 @@
 import org.mockito.Incubating;
 
 /**
- * One parameter function which returns something
+ * Generic interface to be used for configuring mock's answer for a single argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).thenAnswer(new Answer&lt;Integer, String&gt;() {
+ *     Integer answer(String arg) {
+ *         return arg.length();
+ *     }
+ * });
+ *
+ * //Following will print "3"
+ * System.out.println(mock.someMethod("foo"));
+ * </code></pre>
  *
  * @param <T> return type
- * @param <A> input parameter 1 type
+ * @param <A0> type of the single argument
+ * @see Answer
  */
 @Incubating
-public interface Answer1<T, A> {
-    T answer(A a);
+public interface Answer1<T, A0> {
+    /**
+     * @param argument0 the single argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0) throws Throwable;
 }
 
diff --git a/src/main/java/org/mockito/stubbing/Answer2.java b/src/main/java/org/mockito/stubbing/Answer2.java
index 89f1894f29..76ed89192a 100644
--- a/src/main/java/org/mockito/stubbing/Answer2.java
+++ b/src/main/java/org/mockito/stubbing/Answer2.java
@@ -3,13 +3,37 @@
 import org.mockito.Incubating;
 
 /**
- * Two parameter function which returns something
+ * Generic interface to be used for configuring mock's answer for a two argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyChar())).thenAnswer(new Answer&lt;String, String, Character&gt;() {
+ *     String answer(String s, Character c) {
+ *         return s.replace('f', c);
+ *     }
+ * });
+ *
+ * //Following will print "bar"
+ * System.out.println(mock.someMethod("far", 'b'));
+ * </code></pre>
  *
  * @param <T> return type
- * @param <A> input parameter 1 type
- * @param <B> input parameter 2 type
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @see Answer
  */
 @Incubating
-public interface Answer2<T, A, B> {
-    T answer(A a, B b);
+public interface Answer2<T, A0, A1> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0, A1 argument1) throws Throwable;
 }
diff --git a/src/main/java/org/mockito/stubbing/Answer3.java b/src/main/java/org/mockito/stubbing/Answer3.java
index 18b4b22f80..a495872f31 100644
--- a/src/main/java/org/mockito/stubbing/Answer3.java
+++ b/src/main/java/org/mockito/stubbing/Answer3.java
@@ -3,14 +3,40 @@
 import org.mockito.Incubating;
 
 /**
- * Three parameter function which returns something
+ * Generic interface to be used for configuring mock's answer for a three argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyInt(), anyString(), anyChar())).thenAnswer(
+ *     new Answer&lt;StringBuilder, Integer, String, Character&gt;() {
+ *         StringBuilder answer(Integer i, String s, Character c) {
+ *             return new StringBuilder().append(i).append(s).append(c);
+ *         }
+ *     });
+ *
+ * //Following will print "3xyz"
+ * System.out.println(mock.someMethod(3, "xy", 'z'));
+ * </code></pre>
  *
  * @param <T> return type
- * @param <A> input parameter 1 type
- * @param <B> input parameter 2 type
- * @param <C> input parameter 3 type
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @see Answer
  */
 @Incubating
-public interface Answer3<T, A, B, C> {
-    T answer(A a, B b, C c);
+public interface Answer3<T, A0, A1, A2> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0, A1 argument1, A2 argument2) throws Throwable;
 }
diff --git a/src/main/java/org/mockito/stubbing/Answer4.java b/src/main/java/org/mockito/stubbing/Answer4.java
index 286542bf8d..d33484ca91 100644
--- a/src/main/java/org/mockito/stubbing/Answer4.java
+++ b/src/main/java/org/mockito/stubbing/Answer4.java
@@ -3,15 +3,42 @@
 import org.mockito.Incubating;
 
 /**
- * Three parameter function which returns something
+ * Generic interface to be used for configuring mock's answer for a four argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyInt(), anyString(), anyChar(), any())).thenAnswer(
+ *     new Answer&lt;StringBuilder, Integer, String, Character, Object&gt;() {
+ *         StringBuilder answer(Integer i, String s, Character c, Object o) {
+ *             return new StringBuilder().append(i).append(s).append(c).append(o.hashCode());
+ *         }
+ *     });
+ *
+ * //Following will print a string like "3xyz131635550"
+ * System.out.println(mock.someMethod(3, "xy", 'z', new Object()));
+ * </code></pre>
  *
  * @param <T> return type
- * @param <A> input parameter 1 type
- * @param <B> input parameter 2 type
- * @param <C> input parameter 3 type
- * @param <D> input parameter 4 type
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @param <A3> type of the fourth argument
+ * @see Answer
  */
 @Incubating
-public interface Answer4<T, A, B, C, D> {
-    T answer(A a, B b, C c, D d);
+public interface Answer4<T, A0, A1, A2, A3> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     * @param argument3 the fourth argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0, A1 argument1, A2 argument2, A3 argument3) throws Throwable;
 }
diff --git a/src/main/java/org/mockito/stubbing/Answer5.java b/src/main/java/org/mockito/stubbing/Answer5.java
index 87e1734b3f..6231340da7 100644
--- a/src/main/java/org/mockito/stubbing/Answer5.java
+++ b/src/main/java/org/mockito/stubbing/Answer5.java
@@ -3,16 +3,43 @@
 import org.mockito.Incubating;
 
 /**
- * Three parameter function which returns something
+ * Generic interface to be used for configuring mock's answer for a five argument invocation.
+ *
+ * Answer specifies an action that is executed and a return value that is returned when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyInt(), anyString(), anyChar(), any(), anyBoolean())).thenAnswer(
+ *     new Answer&lt;StringBuilder, Integer, String, Character, Object, Boolean&gt;() {
+ *         StringBuilder answer(Integer i, String s, Character c, Object o, Boolean isIt) {
+ *             return new StringBuilder().append(i).append(s).append(c).append(o.hashCode()).append(isIt);
+ *         }
+ *     });
+ *
+ * //Following will print a string like "3xyz131635550true"
+ * System.out.println(mock.someMethod(3, "xy", 'z', new Object(), true));
+ * </code></pre>
  *
  * @param <T> return type
- * @param <A> input parameter 1 type
- * @param <B> input parameter 2 type
- * @param <C> input parameter 3 type
- * @param <D> input parameter 4 type
- * @param <E> input parameter 5 type
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @param <A3> type of the fourth argument
+ * @see Answer
  */
 @Incubating
-public interface Answer5<T, A, B, C, D, E> {
-    T answer(A a, B b, C c, D d, E e);
+public interface Answer5<T, A0, A1, A2, A3, A4> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     * @param argument3 the fourth argument.
+     * @param argument4 the fifth argument.
+     *
+     * @return the value to be returned.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    T answer(A0 argument0, A1 argument1, A2 argument2, A3 argument3, A4 argument4) throws Throwable;
 }
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer1.java b/src/main/java/org/mockito/stubbing/VoidAnswer1.java
index 23717d58e7..8ec93f3d89 100644
--- a/src/main/java/org/mockito/stubbing/VoidAnswer1.java
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer1.java
@@ -3,11 +3,32 @@
 import org.mockito.Incubating;
 
 /**
- * One parameter void function
+ * Generic interface to be used for configuring mock's answer for a single argument invocation that returns nothing.
  *
- * @param <A> input parameter 1 type
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString())).thenAnswer(new Answer&lt;String&gt;() {
+ *     void answer(String msg) {
+ *         throw new Exception(msg);
+ *     }
+ * });
+ *
+ * //Following will raise an exception with the message "boom"
+ * mock.someMethod("boom");
+ * </code></pre>
+ *
+ * @param <A0> type of the single argument
+ * @see Answer
  */
 @Incubating
-public interface VoidAnswer1<A> {
-    void answer(A a);
+public interface VoidAnswer1<A0> {
+    /**
+     * @param argument0 the single argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0) throws Throwable;
 }
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer2.java b/src/main/java/org/mockito/stubbing/VoidAnswer2.java
index 1df3af3e8a..55d594ae6c 100644
--- a/src/main/java/org/mockito/stubbing/VoidAnswer2.java
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer2.java
@@ -3,12 +3,34 @@
 import org.mockito.Incubating;
 
 /**
- * Two parameter void function
+ * Generic interface to be used for configuring mock's answer for a two argument invocation that returns nothing.
  *
- * @param <A> input parameter 1 type
- * @param <B> input parameter 2 type
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt())).thenAnswer(new Answer&lt;String, Integer&gt;() {
+ *     void answer(String msg, Integer count) {
+ *         throw new Exception(String.format(msg, count));
+ *     }
+ * });
+ *
+ * //Following will raise an exception with the message "boom 3"
+ * mock.someMethod("boom %d", 3);
+ * </code></pre>
+ *
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @see Answer
  */
 @Incubating
-public interface VoidAnswer2<A, B> {
-    void answer(A a, B b);
+public interface VoidAnswer2<A0, A1> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0, A1 argument1) throws Throwable;
 }
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer3.java b/src/main/java/org/mockito/stubbing/VoidAnswer3.java
index 21927c50bd..2cdd268817 100644
--- a/src/main/java/org/mockito/stubbing/VoidAnswer3.java
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer3.java
@@ -3,13 +3,36 @@
 import org.mockito.Incubating;
 
 /**
- * Two parameter void function
+ * Generic interface to be used for configuring mock's answer for a three argument invocation that returns nothing.
  *
- * @param <A> input parameter 1 type
- * @param <B> input parameter 2 type
- * @param <C> input parameter 3 type
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt(), anyString())).thenAnswer(new Answer&lt;String, Integer, String&gt;() {
+ *     void answer(String msg, Integer count, String another) {
+ *         throw new Exception(String.format(msg, another, count));
+ *     }
+ * });
+ *
+ * //Following will raise an exception with the message "ka-boom 3"
+ * mock.someMethod("%s-boom %d", 3, "ka");
+ * </code></pre>
+ *
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @see Answer
  */
 @Incubating
-public interface VoidAnswer3<A, B, C> {
-    void answer(A a, B b, C c);
+public interface VoidAnswer3<A0, A1, A2> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0, A1 argument1, A2 argument2) throws Throwable;
 }
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer4.java b/src/main/java/org/mockito/stubbing/VoidAnswer4.java
index 8385e24e2c..939a04add0 100644
--- a/src/main/java/org/mockito/stubbing/VoidAnswer4.java
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer4.java
@@ -3,14 +3,39 @@
 import org.mockito.Incubating;
 
 /**
- * Two parameter void function
+ * Generic interface to be used for configuring mock's answer for a four argument invocation that returns nothing.
  *
- * @param <A> input parameter 1 type
- * @param <B> input parameter 2 type
- * @param <C> input parameter 3 type
- * @param <D> input parameter 4 type
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt(), anyString(), anyChar())).thenAnswer(
+ *     new Answer&lt;String, Integer, String, Character&gt;() {
+ *         void answer(String msg, Integer count, String another, Character c) {
+ *             throw new Exception(String.format(msg, another, c, count));
+ *         }
+ *     });
+ *
+ * //Following will raise an exception with the message "ka-boom <3"
+ * mock.someMethod("%s-boom %c%d", 3, "ka", '&lt;');
+ * </code></pre>
+ *
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @param <A3> type of the fourth argument
+ * @see Answer
  */
 @Incubating
-public interface VoidAnswer4<A, B, C, D> {
-    void answer(A a, B b, C c, D d);
+public interface VoidAnswer4<A0, A1, A2, A3> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     * @param argument3 the fourth argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0, A1 argument1, A2 argument2, A3 argument3) throws Throwable;
 }
diff --git a/src/main/java/org/mockito/stubbing/VoidAnswer5.java b/src/main/java/org/mockito/stubbing/VoidAnswer5.java
index 4fdf9bda73..a92ab9b08f 100644
--- a/src/main/java/org/mockito/stubbing/VoidAnswer5.java
+++ b/src/main/java/org/mockito/stubbing/VoidAnswer5.java
@@ -3,15 +3,41 @@
 import org.mockito.Incubating;
 
 /**
- * Two parameter void function
+ * Generic interface to be used for configuring mock's answer for a five argument invocation that returns nothing.
  *
- * @param <A> input parameter 1 type
- * @param <B> input parameter 2 type
- * @param <C> input parameter 3 type
- * @param <D> input parameter 4 type
- * @param <E> input parameter 5 type
+ * Answer specifies an action that is executed when you interact with the mock.
+ * <p>
+ * Example of stubbing a mock with this custom answer:
+ *
+ * <pre class="code"><code class="java">
+ * when(mock.someMethod(anyString(), anyInt(), anyString(), anyChar(), anyString())).thenAnswer(
+ *     new Answer&lt;String, Integer, String, Character&gt;() {
+ *         void answer(String msg, Integer count, String another, Character c, String subject) {
+ *             throw new Exception(String.format(msg, another, c, count, subject));
+ *         }
+ *     });
+ *
+ * //Following will raise an exception with the message "ka-boom <3 mockito"
+ * mock.someMethod("%s-boom %c%d %s", 3, "ka", '&lt;', "mockito");
+ * </code></pre>
+ *
+ * @param <A0> type of the first argument
+ * @param <A1> type of the second argument
+ * @param <A2> type of the third argument
+ * @param <A3> type of the fourth argument
+ * @param <A4> type of the fifth argument
+ * @see Answer
  */
 @Incubating
-public interface VoidAnswer5<A, B, C, D, E> {
-    void answer(A a, B b, C c, D d, E e);
+public interface VoidAnswer5<A0, A1, A2, A3, A4> {
+    /**
+     * @param argument0 the first argument.
+     * @param argument1 the second argument.
+     * @param argument2 the third argument.
+     * @param argument3 the fourth argument.
+     * @param argument4 the fifth argument.
+     *
+     * @throws Throwable the throwable to be thrown
+     */
+    void answer(A0 argument0, A1 argument1, A2 argument2, A3 argument3, A4 argument4) throws Throwable;
 }


Test patch: