Repository: mockito/mockito
Issue: [VarArgs] unexpected behaviour of returnsArgAt(int)
Labels: bug

I stumble about a test that failed after refactoring an array parameter to an varargs.

The following test succeed:
```java
interface Foo{
        int[] getOdd(int[] input);
}

@Test
public void test() throws Exception {
    when(foo.getOdd(any())).then(returnsArgAt(0));
        
    int[] odd = mock.getOdd(new int[]{1,3,5});
    assertThat(odd).contains(1,3,5);
}
```
Now lets change the parameter _input_ to an varargs.
```java
interface Foo{
        int[] getOdd(int... input);
}
```
The test fails now with:

```
org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
The argument of type 'int' cannot be returned because the following 
method should return the type 'int[]'
 -> foo.getOdd()
```

This is not expected cause the change is source and binary(?) compatible, an varargs-parameter is still an array. ReturnsArgumentAt interprets the vararg array items as real parameters. In other words it tries to return an element type where the array type is required.

Can the behaviour of interpreting vararg elements like parameters be changed so an vararg is treated as an array? E.g. in Mockito 3? There are several other cases were the current vararg handling leads to unexpected behaviour.

Issue comments:
I think your second example has a typo, since there are no var args in the example
thanks fixed
Good catch!
By the way, the mock reference is both foo and mock
While it is source and binary compatible, vararg method are different than plain old array method, reflection allows to distinguish that. The issue is in `ReturnsArgumentAt.returnedTypeOnSignature` where there's a special handling for varargs.
I'm working on the fix (currently adding some unit tests)
This should be fixed by #821

Pull request review comments:
French comment? 😂 
spacing
haha yes, I'm sick, so my brain had to think in french and slowly

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/AdditionalAnswers.java b/src/main/java/org/mockito/AdditionalAnswers.java
index 348743da04..287e4b1830 100644
--- a/src/main/java/org/mockito/AdditionalAnswers.java
+++ b/src/main/java/org/mockito/AdditionalAnswers.java
@@ -36,20 +36,44 @@
  */
 @SuppressWarnings("unchecked")
 public class AdditionalAnswers {
-    private static final ReturnsArgumentAt RETURNS_FIRST_ARGUMENT = new ReturnsArgumentAt(0);
-    private static final ReturnsArgumentAt RETURNS_SECOND_ARGUMENT = new ReturnsArgumentAt(1);
-    private static final ReturnsArgumentAt RETURNS_LAST_ARGUMENT = new ReturnsArgumentAt(-1);
-
     /**
      * Returns the first parameter of an invocation.
      *
      * <p>
      *     This additional answer could be used at stub time using the
      *     <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+     *
+     * <pre class="code"><code class="java">
+     * given(carKeyFob.authenticate(carKey)).will(returnsFirstArg());
+     * doAnswer(returnsFirstArg()).when(carKeyFob).authenticate(carKey);
+     * </code></pre>
      * </p>
      *
-     * <pre class="code"><code class="java">given(carKeyFob.authenticate(carKey)).will(returnsFirstArg());
-     * doAnswer(returnsFirstArg()).when(carKeyFob).authenticate(carKey)</code></pre>
+     * <p>
+     * This methods works with varargs as well, mockito will expand the vararg to return the argument
+     * at the given position. Suppose the following signature :
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream remember(Dream... dreams);
+     * }
+     *
+     * // returns dream1
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsFirstArg());
+     * </code></pre>
+     *
+     * Mockito will return the vararg array if the first argument is a vararg in the method
+     * and if the return type has the same type as the vararg array.
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream[] remember(Dream... otherDreams);
+     * }
+     *
+     * // returns otherDreams (happens to be a 4 elements array)
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsFirstArg());
+     * </code></pre>
+     * </p>
      *
      * @param <T> Return type of the invocation.
      * @return Answer that will return the first argument of the invocation.
@@ -57,7 +81,7 @@ public class AdditionalAnswers {
      * @since 1.9.5
      */
     public static <T> Answer<T> returnsFirstArg() {
-        return (Answer<T>) RETURNS_FIRST_ARGUMENT;
+        return (Answer<T>) new ReturnsArgumentAt(0);
     }
 
     /**
@@ -66,10 +90,38 @@ public static <T> Answer<T> returnsFirstArg() {
      * <p>
      *     This additional answer could be used at stub time using the
      *     <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+     *
+     * <pre class="code"><code class="java">
+     * given(trader.apply(leesFormula, onCreditDefaultSwap)).will(returnsSecondArg());
+     * doAnswer(returnsSecondArg()).when(trader).apply(leesFormula, onCreditDefaultSwap);
+     * </code></pre>
      * </p>
      *
-     * <pre class="code"><code class="java">given(trader.apply(leesFormula, onCreditDefaultSwap)).will(returnsSecondArg());
-     * doAnswer(returnsSecondArg()).when(trader).apply(leesFormula, onCreditDefaultSwap)</code></pre>
+     * <p>
+     * This methods works with varargs as well, mockito will expand the vararg to return the argument
+     * at the given position. Suppose the following signature :
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream remember(Dream dream, Dream... otherDreams);
+     * }
+     *
+     * // returns dream2
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsSecondArg());
+     * </code></pre>
+     *
+     * Mockito will return the vararg array if the second argument is a vararg in the method
+     * and if the return type has the same type as the vararg array.
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream[] remember(Dream dream1, Dream... otherDreams);
+     * }
+     *
+     * // returns otherDreams (happens to be a 3 elements array)
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsSecondArg());
+     * </code></pre>
+     * </p>
      *
      * @param <T> Return type of the invocation.
      * @return Answer that will return the second argument of the invocation.
@@ -77,7 +129,7 @@ public static <T> Answer<T> returnsFirstArg() {
      * @since 1.9.5
      */
     public static <T> Answer<T> returnsSecondArg() {
-        return (Answer<T>) RETURNS_SECOND_ARGUMENT;
+        return (Answer<T>) new ReturnsArgumentAt(1);
     }
 
     /**
@@ -86,10 +138,38 @@ public static <T> Answer<T> returnsSecondArg() {
      * <p>
      *     This additional answer could be used at stub time using the
      *     <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+     *
+     * <pre class="code"><code class="java">
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
+     * doAnswer(returnsLastArg()).when(person).remember(dream1, dream2, dream3, dream4);
+     * </code></pre>
      * </p>
      *
-     * <pre class="code"><code class="java">given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
-     * doAnswer(returnsLastArg()).when(person).remember(dream1, dream2, dream3, dream4)</code></pre>
+     * <p>
+     * This methods works with varargs as well, mockito will expand the vararg to return the argument
+     * at the given position. Suppose the following signature :
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream remember(Dream dream, Dream... otherDreams);
+     * }
+     *
+     * // returns dream4
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
+     * </code></pre>
+     *
+     * Mockito will return the vararg array if the given {@code position} targets the vararg index in the method
+     * and if the return type has the same type as the vararg array.
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream[] remember(Dream dream1, Dream dream2, Dream dream3, Dream... otherDreams);
+     * }
+     *
+     * // returns otherDreams (happens to be a single element array)
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsLastArg());
+     * </code></pre>
+     * </p>
      *
      * @param <T> Return type of the invocation.
      * @return Answer that will return the last argument of the invocation.
@@ -97,7 +177,7 @@ public static <T> Answer<T> returnsSecondArg() {
      * @since 1.9.5
      */
     public static <T> Answer<T> returnsLastArg() {
-        return (Answer<T>) RETURNS_LAST_ARGUMENT;
+        return (Answer<T>) new ReturnsArgumentAt(ReturnsArgumentAt.LAST_ARGUMENT);
     }
 
     /**
@@ -106,10 +186,38 @@ public static <T> Answer<T> returnsLastArg() {
      * <p>
      * This additional answer could be used at stub time using the
      * <code>then|do|will{@link org.mockito.stubbing.Answer}</code> methods. For example :
+     *
+     * <pre class="code"><code class="java">
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(3));
+     * doAnswer(returnsArgAt(3)).when(person).remember(dream1, dream2, dream3, dream4);
+     * </code></pre>
      * </p>
      *
-     * <pre class="code"><code class="java">given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(3));
-     * doAnswer(returnsArgAt(3)).when(person).remember(dream1, dream2, dream3, dream4)</code></pre>
+     * <p>
+     * This methods works with varargs as well, mockito will expand the vararg to return the argument
+     * at the given position. Suppose the following signature :
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream remember(Dream dream, Dream... otherDreams);
+     * }
+     *
+     * // returns dream 3
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(2));
+     * </code></pre>
+     *
+     * Mockito will return the vararg array if the given {@code position} targets the vararg index in the method
+     * and if the return type has the same type as the vararg array.
+     *
+     * <pre class="code"><code class="java">
+     * interface Person {
+     *     Dream[] remember(Dream dream, Dream... otherDreams);
+     * }
+     *
+     * // returns otherDreams array (contains dream2, dream,3, dream4)
+     * given(person.remember(dream1, dream2, dream3, dream4)).will(returnsArgAt(1));
+     * </code></pre>
+     * </p>
      *
      * @param <T> Return type of the invocation.
      * @param position index of the argument from the list of arguments.
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java b/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java
index c22746b568..7c0a144b71 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java
@@ -5,17 +5,16 @@
 package org.mockito.internal.stubbing.answers;
 
 import java.io.Serializable;
+import java.lang.reflect.Method;
+import org.mockito.internal.exceptions.Reporter;
+import org.mockito.invocation.Invocation;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 import org.mockito.stubbing.ValidableAnswer;
 
-import static org.mockito.internal.exceptions.Reporter.invalidArgumentPositionRangeAtInvocationTime;
-import static org.mockito.internal.exceptions.Reporter.invalidArgumentRangeAtIdentityAnswerCreationTime;
-import static org.mockito.internal.exceptions.Reporter.wrongTypeOfArgumentToReturn;
-
 /**
  * Returns the passed parameter identity at specified index.
- *
+ * <p>
  * <p>The <code>argumentIndex</code> represents the index in the argument array of the invocation.</p>
  * <p>If this number equals -1 then the last argument is returned.</p>
  *
@@ -34,92 +33,102 @@ public class ReturnsArgumentAt implements Answer<Object>, ValidableAnswer, Seria
      * Build the identity answer to return the argument at the given position in the argument array.
      *
      * @param wantedArgumentPosition The position of the argument identity to return in the invocation.
-     *                      Using <code>-1</code> indicates the last argument.
+     *                               Using <code>-1</code> indicates the last argument ({@link #LAST_ARGUMENT}).
      */
     public ReturnsArgumentAt(int wantedArgumentPosition) {
-        this.wantedArgumentPosition = checkWithinAllowedRange(wantedArgumentPosition);
-    }
-
-    public Object answer(InvocationOnMock invocation) throws Throwable {
-        validateIndexWithinInvocationRange(invocation);
-        return invocation.getArgument(actualArgumentPosition(invocation));
+        if (wantedArgumentPosition != LAST_ARGUMENT && wantedArgumentPosition < 0) {
+            throw Reporter.invalidArgumentRangeAtIdentityAnswerCreationTime();
+        }
+        this.wantedArgumentPosition = wantedArgumentPosition;
     }
 
     @Override
-    public void validateFor(InvocationOnMock invocation) {
-        validateIndexWithinInvocationRange(invocation);
+    public Object answer(InvocationOnMock invocation) throws Throwable {
+        int argumentPosition = inferWantedArgumentPosition(invocation);
+        validateIndexWithinInvocationRange(invocation, argumentPosition);
 
-        InvocationInfo invocationInfo = new InvocationInfo(invocation);
-        if (!invocationInfo.isValidReturnType(returnedTypeOnSignature(invocation))) {
-            throw wrongTypeOfArgumentToReturn(invocation, invocationInfo.printMethodReturnType(),
-                                              returnedTypeOnSignature(invocation),
-                                              wantedArgumentPosition());
+        if (wantedArgIndexIsVarargAndSameTypeAsReturnType(invocation.getMethod(), argumentPosition)) {
+            // answer raw vararg array argument
+            return ((Invocation) invocation).getRawArguments()[argumentPosition];
+        } else {
+            // answer expanded argument at wanted position
+            return invocation.getArgument(argumentPosition);
         }
     }
 
-    private int actualArgumentPosition(InvocationOnMock invocation) {
-        return returningLastArg() ?
-                lastArgumentIndexOf(invocation) :
-                argumentIndexOf(invocation);
-    }
-
-    private boolean returningLastArg() {
-        return wantedArgumentPosition == LAST_ARGUMENT;
+    @Override
+    public void validateFor(InvocationOnMock invocation) {
+        int argumentPosition = inferWantedArgumentPosition(invocation);
+        validateIndexWithinInvocationRange(invocation, argumentPosition);
+        validateArgumentTypeCompatibility(invocation, argumentPosition);
     }
 
-    private int argumentIndexOf(InvocationOnMock invocation) {
-        return wantedArgumentPosition;
+    private int inferWantedArgumentPosition(InvocationOnMock invocation) {
+        return wantedArgumentPosition == LAST_ARGUMENT ?
+               invocation.getArguments().length - 1 :
+               wantedArgumentPosition;
     }
 
-    private int lastArgumentIndexOf(InvocationOnMock invocation) {
-        return invocation.getArguments().length - 1;
+    private void validateIndexWithinInvocationRange(InvocationOnMock invocation, int argumentPosition) {
+        if (!wantedArgumentPositionIsValidForInvocation(invocation, argumentPosition)) {
+            throw Reporter.invalidArgumentPositionRangeAtInvocationTime(invocation,
+                                                                        wantedArgumentPosition == LAST_ARGUMENT,
+                                                                        wantedArgumentPosition);
+        }
     }
 
-    private int checkWithinAllowedRange(int argumentPosition) {
-        if (argumentPosition != LAST_ARGUMENT && argumentPosition < 0) {
-            throw invalidArgumentRangeAtIdentityAnswerCreationTime();
+    private void validateArgumentTypeCompatibility(InvocationOnMock invocation, int argumentPosition) {
+        InvocationInfo invocationInfo = new InvocationInfo(invocation);
+        Class<?> inferredArgumentType = inferWantedArgumentType(invocation, argumentPosition);
+        if (!invocationInfo.isValidReturnType(inferredArgumentType)) {
+            throw Reporter.wrongTypeOfArgumentToReturn(invocation,
+                                                       invocationInfo.printMethodReturnType(),
+                                                       inferredArgumentType,
+                                                       wantedArgumentPosition);
         }
-        return argumentPosition;
     }
 
-    private int wantedArgumentPosition() {
-        return wantedArgumentPosition;
+    private boolean wantedArgIndexIsVarargAndSameTypeAsReturnType(Method method, int argumentPosition) {
+        Class<?>[] parameterTypes = method.getParameterTypes();
+        return method.isVarArgs()
+               && argumentPosition == /* vararg index */ parameterTypes.length - 1
+               && method.getReturnType().isAssignableFrom(parameterTypes[argumentPosition]);
     }
 
-    private void validateIndexWithinInvocationRange(InvocationOnMock invocation) {
-        if (!argumentPositionInRange(invocation)) {
-            throw invalidArgumentPositionRangeAtInvocationTime(invocation,
-                                                               returningLastArg(),
-                                                               wantedArgumentPosition);
-        }
-    }
-
-    private boolean argumentPositionInRange(InvocationOnMock invocation) {
-        int actualArgumentPosition = actualArgumentPosition(invocation);
-        if (actualArgumentPosition < 0) {
+    private boolean wantedArgumentPositionIsValidForInvocation(InvocationOnMock invocation, int argumentPosition) {
+        if (argumentPosition < 0) {
             return false;
         }
         if (!invocation.getMethod().isVarArgs()) {
-            return invocation.getArguments().length > actualArgumentPosition;
+            return invocation.getArguments().length > argumentPosition;
         }
         // for all varargs accepts positive ranges
         return true;
     }
 
-    private Class<?> returnedTypeOnSignature(InvocationOnMock invocation) {
-        int actualArgumentPosition = actualArgumentPosition(invocation);
-
-        if(!invocation.getMethod().isVarArgs()) {
-            return invocation.getMethod().getParameterTypes()[actualArgumentPosition];
+    private Class<?> inferWantedArgumentType(InvocationOnMock invocation, int argumentPosition) {
+        Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
+        // Easy when the method is not a vararg
+        if (!invocation.getMethod().isVarArgs()) {
+            return parameterTypes[argumentPosition];
         }
 
-        Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
-        int varargPosition = parameterTypes.length - 1;
+        // Now for varargs
+        int varargIndex = parameterTypes.length - 1; // vararg always last
 
-        if(actualArgumentPosition < varargPosition) {
-            return parameterTypes[actualArgumentPosition];
+        if (argumentPosition < varargIndex) {
+            // Same for non vararg arguments
+            return parameterTypes[argumentPosition];
         } else {
-            return parameterTypes[varargPosition].getComponentType();
+            // if wanted argument is vararg
+            if (wantedArgIndexIsVarargAndSameTypeAsReturnType(invocation.getMethod(), argumentPosition)) {
+                // return the vararg array if return type is compatible
+                // because the user probably want to return the array itself if the return type is compatible
+                return parameterTypes[argumentPosition]; // move to MethodInfo ?
+            } else {
+                // return the type in this vararg array
+                return parameterTypes[varargIndex].getComponentType();
+            }
         }
     }
 }


Test patch:
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAtTest.java b/src/test/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAtTest.java
index 5ccdbd0926..f72005aeaa 100644
--- a/src/test/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAtTest.java
+++ b/src/test/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAtTest.java
@@ -4,10 +4,12 @@
  */
 package org.mockito.internal.stubbing.answers;
 
+import org.assertj.core.api.Assertions;
 import org.junit.Test;
 import org.mockito.exceptions.base.MockitoException;
 import org.mockito.exceptions.misusing.WrongTypeOfReturnValue;
 import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
 import org.mockito.invocation.InvocationOnMock;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -38,27 +40,82 @@ public void should_be_able_to_return_the_specified_parameter() throws Throwable
         assertThat(new ReturnsArgumentAt(2).answer(invocationWith("A", "B", "C"))).isEqualTo("C");
     }
 
+    @Test
+    public void should_identify_bad_parameter_type_for_invocation() throws Exception {
+        try {
+            new ReturnsArgumentAt(1).validateFor(new InvocationBuilder().method("varargsReturningString")
+                                                                        .argTypes(Object[].class)
+                                                                        .args(new Object(), new Object(), new Object())
+                                                                        .toInvocation());
+            Assertions.fail("should scream");
+        } catch (WrongTypeOfReturnValue ignored) { }
+        try {
+            new ReturnsArgumentAt(0).validateFor(new InvocationBuilder().method("oneArray")
+                                                                        .argTypes(boolean[].class)
+                                                                        .args(true, false, false)
+                                                                        .toInvocation());
+            Assertions.fail("should scream");
+        } catch (WrongTypeOfReturnValue ignored) { }
+        try {
+            new ReturnsArgumentAt(0).validateFor(new InvocationBuilder().method("mixedVarargsReturningString")
+                                                                        .argTypes(Object.class, String[].class)
+                                                                        .args(new Object(), new String[]{"A", "B", "C"})
+                                                                        .toInvocation());
+            Assertions.fail("should scream");
+        } catch (WrongTypeOfReturnValue ignored) { }
+    }
+
+    @Test
+    public void should_not_scream_when_mixed_vararg_parameter_is_compatible_with_invocation() throws Exception {
+        new ReturnsArgumentAt(1).validateFor(new InvocationBuilder().method("mixedVarargsReturningString")
+                                                                    .argTypes(Object.class, String[].class)
+                                                                    .args(new Object(), new String[]{"A", "B", "C"})
+                                                                    .toInvocation());
+    }
+
+        @Test
+    public void should_handle_returning_vararg_as_array() throws Throwable {
+        Invocation mixedVarargsReturningStringArray = new InvocationBuilder().method("mixedVarargsReturningStringArray")
+                                                                             .argTypes(Object.class, String[].class)
+                                                                             .args(new Object(), new String[]{"A", "B", "C"})
+                                                                             .toInvocation();
+        new ReturnsArgumentAt(1).validateFor(mixedVarargsReturningStringArray);
+        assertThat(new ReturnsArgumentAt(1).answer(mixedVarargsReturningStringArray)).isEqualTo(new String[]{"A", "B", "C"});
+
+        Invocation mixedVarargsReturningObjectArray = new InvocationBuilder().method("mixedVarargsReturningStringArray")
+                                                                             .argTypes(Object.class, String[].class)
+                                                                             .args(new Object(), new String[]{"A", "B", "C"})
+                                                                             .toInvocation();
+        new ReturnsArgumentAt(1).validateFor(mixedVarargsReturningObjectArray);
+        assertThat(new ReturnsArgumentAt(1).answer(mixedVarargsReturningObjectArray)).isEqualTo(new String[]{"A", "B", "C"});
+    }
+
     @Test
     public void should_raise_an_exception_if_index_is_not_in_allowed_range_at_creation_time() throws Throwable {
         try {
             new ReturnsArgumentAt(-30);
             fail();
         } catch (Exception e) {
-            assertThat(e.getMessage())
-                    .containsIgnoringCase("argument index")
-                    .containsIgnoringCase("positive number")
-                    .contains("1")
-                    .containsIgnoringCase("last argument");
+            assertThat(e.getMessage()).containsIgnoringCase("argument index")
+                                      .containsIgnoringCase("positive number")
+                                      .contains("1")
+                                      .containsIgnoringCase("last argument");
         }
     }
 
     @Test
     public void should_allow_possible_argument_types() throws Exception {
         new ReturnsArgumentAt(0).validateFor(
-                new InvocationBuilder().method("intArgumentReturningInt").argTypes(int.class).arg(1000).toInvocation()
+                new InvocationBuilder().method("intArgumentReturningInt")
+                                       .argTypes(int.class)
+                                       .arg(1000)
+                                       .toInvocation()
         );
         new ReturnsArgumentAt(0).validateFor(
-                new InvocationBuilder().method("toString").argTypes(String.class).arg("whatever").toInvocation()
+                new InvocationBuilder().method("toString")
+                                       .argTypes(String.class)
+                                       .arg("whatever")
+                                       .toInvocation()
         );
         new ReturnsArgumentAt(2).validateFor(
                 new InvocationBuilder().method("varargsObject")
@@ -77,7 +134,9 @@ public void should_allow_possible_argument_types() throws Exception {
     @Test
     public void should_fail_if_index_is_not_in_range_for_one_arg_invocation() throws Throwable {
         try {
-            new ReturnsArgumentAt(30).validateFor(new InvocationBuilder().method("oneArg").arg("A").toInvocation());
+            new ReturnsArgumentAt(30).validateFor(new InvocationBuilder().method("oneArg")
+                                                                         .arg("A")
+                                                                         .toInvocation());
             fail();
         } catch (MockitoException e) {
             assertThat(e.getMessage())
@@ -127,7 +186,8 @@ public void should_fail_if_argument_type_of_signature_is_incompatible_with_retur
     }
 
     private static InvocationOnMock invocationWith(Object... parameters) {
-        return new InvocationBuilder().method("varargsReturningString").argTypes(Object[].class)
+        return new InvocationBuilder().method("varargsReturningString")
+                                      .argTypes(Object[].class)
                                       .args(parameters).toInvocation();
     }
 
diff --git a/src/test/java/org/mockitousage/IMethods.java b/src/test/java/org/mockitousage/IMethods.java
index 7234bd7976..c3d510f5ac 100644
--- a/src/test/java/org/mockitousage/IMethods.java
+++ b/src/test/java/org/mockitousage/IMethods.java
@@ -172,6 +172,12 @@ public interface IMethods {
 
     void mixedVarargs(Object i, String ... string);
 
+    String mixedVarargsReturningString(Object i, String ... string);
+
+    String[] mixedVarargsReturningStringArray(Object i, String ... string);
+
+    Object[] mixedVarargsReturningObjectArray(Object i, String ... string);
+
     List<String> listReturningMethod(Object ... objects);
 
     LinkedList<String> linkedListReturningMethod();
@@ -225,4 +231,4 @@ public interface IMethods {
     Integer toIntWrapper(int i);
 
     String forObject(Object object);
-}
\ No newline at end of file
+}
diff --git a/src/test/java/org/mockitousage/MethodsImpl.java b/src/test/java/org/mockitousage/MethodsImpl.java
index 4f4bdcc8d8..0fb965c3ae 100644
--- a/src/test/java/org/mockitousage/MethodsImpl.java
+++ b/src/test/java/org/mockitousage/MethodsImpl.java
@@ -328,6 +328,18 @@ public int varargs(String... string) {
     public void mixedVarargs(Object i, String... string) {
     }
 
+    public String mixedVarargsReturningString(Object i, String... string) {
+        return null;
+    }
+
+    public String[] mixedVarargsReturningStringArray(Object i, String... string) {
+        return null;
+    }
+
+    public Object[] mixedVarargsReturningObjectArray(Object i, String... string) {
+        return null;
+    }
+
     public void varargsbyte(byte... bytes) {
     }