Repository: mockito/mockito
Issue: Vararg method call on mock object fails when used org.mockito.AdditionalAnswers#delegatesTo

I try to mock interface with varargs method and default implementation in final class and get this error:

```
java.lang.IllegalArgumentException: wrong number of arguments

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.mockito.internal.stubbing.defaultanswers.ForwardsInvocations.answer(ForwardsInvocations.java:31)
    at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:93)
    at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
    at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:38)
    at org.mockito.internal.creation.MethodInterceptorFilter.intercept(MethodInterceptorFilter.java:51)
```

I run the following code:

``` java
public class DefaultAnswerDemo {

    public interface Foo {
        void bar(String baz, Object... args);
    }

    public static final class FooImpl implements Foo {

        @Override
        public void bar(String baz, Object... args) {
            System.out.println("bar");
        }

    }

    @Test
    public void defaultAnswerTest() {
        Foo fooImpl = new FooImpl();

        Foo foo = mock(Foo.class, withSettings()
                .defaultAnswer(delegatesTo(fooImpl)));

        foo.bar("baz", 12, "45", 67.8);
    }

}
```

This is happens because org.mockito.internal.invocation.InvocationImpl by default expands varargs arguments to flat list. And I have no idea, how correctly fix this.


Issue comments:
This is a bug in [ForwardsInvocations](https://github.com/mockito/mockito/blob/master/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java#L41), as you already investigated the expanded varargs are passed to the delegate.

The current implementation does this:

```
result = delegateMethod.invoke(delegatedObject, arguments);
```

Mockito look for method with the signature `String,int,String,double` for the given arguments ("baz",12,"45",67.8), but such a method doesn't exists.

To fix the issue the raw/unexpanded arguments must be used

```
Object[] rawArguments = ((Invocation)invocation).getRawArguments(); 
result = delegateMethod.invoke(delegatedObject, rawArguments);
```

Now Mockito looks for method signature `String,Object[]` which is the var args method you want. Note: It is safe to cast to `Invocation` here cause answers always get a Invocation-Instance passed from `MockHandlerImpl`. 

If I find some time I will send a PR with a fix or you or some one else start to fix it. 

Here is PR. I thought about cast, but may be better pull up method [org.mockito.invocation.Invocation#getRawArguments](https://github.com/mockito/mockito/blob/master/src/main/java/org/mockito/invocation/Invocation.java#L42) to interface [org.mockito.invocation.InvocationOnMock](https://github.com/mockito/mockito/blob/master/src/main/java/org/mockito/invocation/InvocationOnMock.java)?

@andreyrmg 
Pulling `getRawArguments()` up to `InvocationOnMock` would help in this narrow use case. On the other side it bloat the public API and migth confuse clients that implement custom Answer's, which method to choose `getArguments()` or `getRawArguments()`.  

WDYT?

Yes, I agree with you. But I think, this is already a bit confusing that method `getArgument()` returns expanded varargs. Maybe we need two methods `getArguments()` and `getExpandedArguments()`?

Adding new API or changing existing behaviour need to be discussed with the core-members.

I agree with you, `getArguments()` should return unaltered/not expanded arguments. The current `getArguments()` implementation has also the problem that is can't distinguish an null-vararg argument / `varArgMethod(new Type[]{null})` from an null-varag array / `varArgMethod((Type[])null)`.


Pull request review comments:
- Looks good, can you split the test cases (empty array/ non empty array) ?
- Can you also add a test for `invocationOf(Foo.class, "bar", "baz", new Object[] {null})` and `invocationOf(Foo.class, "bar", "baz", null)` 
- Would you mind using AssertJ's Assertions.assertThat(..).is(..), it is more readable IMHO?

There is no need to extend from `TestBase`, right?


Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java
index 1916a62ce2..95da223adf 100644
--- a/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java
+++ b/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java
@@ -9,6 +9,7 @@
 import java.lang.reflect.Method;
 
 import org.mockito.exceptions.Reporter;
+import org.mockito.invocation.Invocation;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
@@ -37,8 +38,9 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
             if (!compatibleReturnTypes(mockMethod.getReturnType(), delegateMethod.getReturnType())) {
                 new Reporter().delegatedMethodHasWrongReturnType(mockMethod, delegateMethod, invocation.getMock(), delegatedObject);
             }
-            
-            result = delegateMethod.invoke(delegatedObject, invocation.getArguments());
+
+            Object[] rawArguments = ((Invocation) invocation).getRawArguments();
+            result = delegateMethod.invoke(delegatedObject, rawArguments);
         } catch (NoSuchMethodException e) {
             new Reporter().delegatedMethodDoesNotExistOnDelegate(mockMethod, invocation.getMock(), delegatedObject);
         } catch (InvocationTargetException e) {


Test patch:
diff --git a/src/test/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocationsTest.java b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocationsTest.java
new file mode 100644
index 0000000000..42234edc08
--- /dev/null
+++ b/src/test/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocationsTest.java
@@ -0,0 +1,30 @@
+package org.mockito.internal.stubbing.defaultanswers;
+
+import org.junit.Test;
+import org.mockitoutil.TestBase;
+
+public class ForwardsInvocationsTest extends TestBase {
+
+    interface Foo {
+        int bar(String baz, Object... args);
+    }
+
+    private static final class FooImpl implements Foo {
+        @Override
+        public int bar(String baz, Object... args) {
+            return baz.length() + args.length;
+        }
+    }
+
+    @Test
+    public void should_call_method_with_varargs() throws Throwable {
+        ForwardsInvocations forwardsInvocations = new ForwardsInvocations(new FooImpl());
+        assertEquals(4, forwardsInvocations.answer(invocationOf(Foo.class, "bar", "b", new Object[] {12, "3", 4.5})));
+    }
+
+    @Test
+    public void should_call_method_with_empty_varargs() throws Throwable {
+        ForwardsInvocations forwardsInvocations = new ForwardsInvocations(new FooImpl());
+        assertEquals(1, forwardsInvocations.answer(invocationOf(Foo.class, "bar", "b", new Object[] {})));
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateVarArgsTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateVarArgsTest.java
new file mode 100644
index 0000000000..5f41d7178a
--- /dev/null
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWithDelegateVarArgsTest.java
@@ -0,0 +1,46 @@
+package org.mockitousage.stubbing;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.AdditionalAnswers.delegatesTo;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
+
+public class StubbingWithDelegateVarArgsTest {
+
+    public interface Foo {
+        int bar(String baz, Object... args);
+    }
+
+    private static final class FooImpl implements Foo {
+
+        @Override
+        public int bar(String baz, Object... args) {
+            return args != null ? args.length : -1; // simple return argument count
+        }
+
+    }
+
+    @Test
+    public void should_not_fail_when_calling_varargs_method() {
+        Foo foo = mock(Foo.class, withSettings()
+                .defaultAnswer(delegatesTo(new FooImpl())));
+        assertThat(foo.bar("baz", 12, "45", 67.8)).isEqualTo(3);
+    }
+
+    @Test
+    public void should_not_fail_when_calling_varargs_method_without_arguments() {
+        Foo foo = mock(Foo.class, withSettings()
+                .defaultAnswer(delegatesTo(new FooImpl())));
+        assertThat(foo.bar("baz")).isEqualTo(0);
+        assertThat(foo.bar("baz", new Object[0])).isEqualTo(0);
+    }
+
+    @Test
+    public void should_not_fail_when_calling_varargs_method_with_null_argument() {
+        Foo foo = mock(Foo.class, withSettings()
+                .defaultAnswer(delegatesTo(new FooImpl())));
+        assertThat(foo.bar("baz", (Object[]) null)).isEqualTo(-1);
+    }
+}