Repository: mockito/mockito
Issue: Mockito can't unbox Void

Hi,

The following [bug](https://github.com/powermock/powermock/issues/708) was created for PowerMock:  

> PowerMockito doesn't seem to unbox java.lang.Void.
> I am writing a test for my code that uses Google cloud storage API to delete a file. Google API returns Void for deleting a file. Code works fine but when I instruct my test as PowerMockito.doNothing().when(delete).execute(); It complains that execute has a return value of Void.

But PowerMock just delegates call to Mockito in this case and Mockito throws exception: 

```
org.mockito.exceptions.base.MockitoException: 
Only void methods can doNothing()!
Example of correct use of doNothing():
    doNothing().
    doThrow(new RuntimeException())
    .when(mock).someVoidMethod();
Above means:
someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called
```

I have doubts about expected behaviour. For one side, method return something, but it return a `Void` which always is just `Void` and nothing could be changed. 

Anyway, it could be fixed only on Mockito side (without dirty hacks). 

Issue comments:

Pull request review comments:
Spacing around `=`
Very nice! Thank you for updating the documentation diligently.

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/internal/stubbing/StubberImpl.java b/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
index 9f1f8db523..f768cc829f 100644
--- a/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
+++ b/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
@@ -6,12 +6,12 @@
 
 import static org.mockito.internal.exceptions.Reporter.notAMockPassedToWhenMethod;
 import static org.mockito.internal.exceptions.Reporter.nullPassedToWhenMethod;
+import static org.mockito.internal.stubbing.answers.DoesNothing.doesNothing;
 
 import java.util.LinkedList;
 import java.util.List;
 
 import org.mockito.internal.stubbing.answers.CallsRealMethods;
-import org.mockito.internal.stubbing.answers.DoesNothing;
 import org.mockito.internal.stubbing.answers.Returns;
 import org.mockito.internal.stubbing.answers.ThrowsException;
 import org.mockito.internal.stubbing.answers.ThrowsExceptionClass;
@@ -24,6 +24,7 @@ public class StubberImpl implements Stubber {
 
     private final List<Answer<?>> answers = new LinkedList<Answer<?>>();
 
+    @Override
     public <T> T when(T mock) {
         if (mock == null) {
             throw nullPassedToWhenMethod();
@@ -37,10 +38,12 @@ public <T> T when(T mock) {
         return mock;
     }
 
+    @Override
     public Stubber doReturn(Object toBeReturned) {
         return doReturnValues(toBeReturned);
     }
 
+    @Override
     public Stubber doReturn(Object toBeReturned, Object... nextToBeReturned) {
         return doReturnValues(toBeReturned).doReturnValues(nextToBeReturned);
     }
@@ -56,6 +59,7 @@ private StubberImpl doReturnValues(Object... toBeReturned) {
         return this;
     }
 
+    @Override
     public Stubber doThrow(Throwable... toBeThrown) {
         if(toBeThrown == null) {
             answers.add(new ThrowsException(null));
@@ -67,10 +71,12 @@ public Stubber doThrow(Throwable... toBeThrown) {
         return this;
     }
 
+    @Override
     public Stubber doThrow(Class<? extends Throwable> toBeThrown) {
         return doThrowClasses(toBeThrown);
     }
 
+    @Override
     public Stubber doThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown) {
         return doThrowClasses(toBeThrown).doThrowClasses(nextToBeThrown);
     }
@@ -82,16 +88,19 @@ private StubberImpl doThrowClasses(Class<? extends Throwable>... toBeThrown) {
         return this;
     }
 
+    @Override
     public Stubber doNothing() {
-        answers.add(new DoesNothing());
+        answers.add(doesNothing());
         return this;
     }
 
+    @Override
     public Stubber doAnswer(Answer answer) {
         answers.add(answer);
         return this;
     }
 
+    @Override
     public Stubber doCallRealMethod() {
         answers.add(new CallsRealMethods());
         return this;
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java b/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java
index 5d723b3ade..81e85144ee 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java
@@ -16,7 +16,16 @@ public class DoesNothing implements Answer<Object>, ValidableAnswer, Serializabl
 
     private static final long serialVersionUID = 4840880517740698416L;
 
-    public Object answer(InvocationOnMock invocation) throws Throwable {
+    private static final DoesNothing SINGLETON = new DoesNothing();
+    
+    private DoesNothing() {}
+    
+    public static DoesNothing doesNothing(){
+        return SINGLETON;
+    }
+    
+    @Override
+    public Object answer(InvocationOnMock invocation){
         return null;
     }
 
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/InvocationInfo.java b/src/main/java/org/mockito/internal/stubbing/answers/InvocationInfo.java
index a405b94cac..11498b793d 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/InvocationInfo.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/InvocationInfo.java
@@ -38,8 +38,13 @@ public boolean isValidReturnType(Class<?> clazz) {
         }
     }
 
+    /**
+     * Returns {@code true} is the return type is {@link Void} or represents the pseudo-type to the keyword {@code void}.
+     * E.g:  {@code void foo()} or {@code Void bar()}
+     */
     public boolean isVoid() {
-        return this.method.getReturnType() == Void.TYPE;
+        Class<?> returnType = this.method.getReturnType();
+        return returnType == Void.TYPE|| returnType == Void.class;
     }
 
     public String printMethodReturnType() {
@@ -62,6 +67,7 @@ public boolean isDeclaredOnInterface() {
         return method.getDeclaringClass().isInterface();
     }
 
+    @Override
     public boolean isAbstract() {
         return (method.getModifiers() & Modifier.ABSTRACT) != 0;
     }


Test patch:
diff --git a/src/test/java/org/mockito/internal/junit/UnusedStubbingsTest.java b/src/test/java/org/mockito/internal/junit/UnusedStubbingsTest.java
index 5ea343a6c3..cfff121d7e 100644
--- a/src/test/java/org/mockito/internal/junit/UnusedStubbingsTest.java
+++ b/src/test/java/org/mockito/internal/junit/UnusedStubbingsTest.java
@@ -11,6 +11,7 @@
 
 import static java.util.Arrays.asList;
 import static org.junit.Assert.assertEquals;
+import static org.mockito.internal.stubbing.answers.DoesNothing.doesNothing;
 
 public class UnusedStubbingsTest extends TestBase {
 
@@ -32,8 +33,8 @@ public void no_unused_stubbings() throws Exception {
     public void unused_stubbings() throws Exception {
         //given
         UnusedStubbings stubbings = new UnusedStubbings((List) asList(
-            new StubbedInvocationMatcher(new InvocationBuilder().toInvocationMatcher(), new DoesNothing()),
-            new StubbedInvocationMatcher(new InvocationBuilder().toInvocationMatcher(), new DoesNothing())
+            new StubbedInvocationMatcher(new InvocationBuilder().toInvocationMatcher(), doesNothing()),
+            new StubbedInvocationMatcher(new InvocationBuilder().toInvocationMatcher(), doesNothing())
         ));
 
 
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/DoesNothingTest.java b/src/test/java/org/mockito/internal/stubbing/answers/DoesNothingTest.java
index 668bf82d56..06f950e2ba 100644
--- a/src/test/java/org/mockito/internal/stubbing/answers/DoesNothingTest.java
+++ b/src/test/java/org/mockito/internal/stubbing/answers/DoesNothingTest.java
@@ -4,25 +4,59 @@
  */
 package org.mockito.internal.stubbing.answers;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.internal.stubbing.answers.DoesNothing.doesNothing;
+import static org.mockitoutil.TestBase.getLastInvocation;
+
+import org.junit.Before;
 import org.junit.Test;
 import org.mockito.exceptions.base.MockitoException;
-import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
 
-import static org.assertj.core.api.Assertions.assertThat;
+public class DoesNothingTest   {
+    
+    private IMethods mock;
+    private Invocation invocation_Void;
+    private Invocation invocation_void;
+    private Invocation invocation_String;
 
-public class DoesNothingTest {
+    @Before
+    public void init(){
+        mock = mock(IMethods.class);
+        
+        mock.voidMethod();
+        invocation_Void = getLastInvocation();
+        
+        mock.voidReturningMethod();
+        invocation_void = getLastInvocation();
+        
+        mock.simpleMethod();
+        invocation_String = getLastInvocation();
+    }
+    
     @Test
-    public void should_do_nothing() throws Throwable {
-        assertThat(new DoesNothing().answer(new InvocationBuilder().method("voidMethod").toInvocation())).isNull();
+    public void answer_returnsNull() throws Throwable {
+        assertThat(doesNothing().answer(invocation_Void)).isNull();
+        assertThat(doesNothing().answer(invocation_void)).isNull();
+        assertThat(doesNothing().answer(invocation_String)).isNull();
     }
 
     @Test(expected = MockitoException.class)
-    public void should_fail_when_non_void_method_does_nothing() throws Throwable {
-        new DoesNothing().validateFor(new InvocationBuilder().simpleMethod().toInvocation());
+    public void validateFor_nonVoidReturnType_shouldFail()   {
+        doesNothing().validateFor(invocation_String);
     }
 
     @Test
-    public void should_allow_void_return_for_void_method() throws Throwable {
-        new DoesNothing().validateFor(new InvocationBuilder().method("voidMethod").toInvocation());
+    public void validateFor_voidReturnType_shouldPass()   {
+        doesNothing().validateFor(invocation_void);
+    }
+    
+    @Test
+    public void validateFor_voidObjectReturnType() throws Throwable {
+        doesNothing().validateFor(invocation_Void);
     }
+    
+    
 }
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/InvocationInfoTest.java b/src/test/java/org/mockito/internal/stubbing/answers/InvocationInfoTest.java
index f104972858..6d4a1ab5db 100644
--- a/src/test/java/org/mockito/internal/stubbing/answers/InvocationInfoTest.java
+++ b/src/test/java/org/mockito/internal/stubbing/answers/InvocationInfoTest.java
@@ -7,10 +7,17 @@
 import java.lang.reflect.Method;
 import java.nio.charset.CharacterCodingException;
 import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.internal.invocation.InvocationBuilder;
 import org.mockito.invocation.Invocation;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockitoutil.TestBase.getLastInvocation;
 
 public class InvocationInfoTest {
 
@@ -69,6 +76,33 @@ public void should_know_method_is_declared_on_interface() throws Exception {
         assertThat(new InvocationInfo(new InvocationBuilder().method(iAmAbstract()).toInvocation()).isDeclaredOnInterface()).isFalse();
         assertThat(new InvocationInfo(new InvocationBuilder().method("voidMethod").toInvocation()).isDeclaredOnInterface()).isTrue();
     }
+    
+    @Test
+    public void isVoid_invocationOnVoidMethod_returnTrue(){
+        mock(IMethods.class).voidMethod();
+        
+        InvocationInfo voidMethod = new InvocationInfo(getLastInvocation());
+        
+        assertThat(voidMethod.isVoid()).isTrue();
+    }
+    
+    @Test
+    public void isVoid_invocationOnVoidReturningMethod_returnTrue(){
+        mock(IMethods.class).voidReturningMethod();
+        
+        InvocationInfo voidRetuningMethod = new InvocationInfo(getLastInvocation());
+        
+        assertThat(voidRetuningMethod.isVoid()).isTrue();
+    }
+    
+    @Test
+    public void isVoid_invocationNonVoidMethod_returnFalse(){
+        mock(IMethods.class).simpleMethod();
+        
+        InvocationInfo stringReturningMethod = new InvocationInfo(getLastInvocation());
+        
+        assertThat(stringReturningMethod.isVoid()).isFalse();
+    }
 
     private Method iAmAbstract() throws NoSuchMethodException {
         abstract class TheAbstract {
@@ -76,6 +110,7 @@ abstract class TheAbstract {
         }
         return TheAbstract.class.getDeclaredMethod("iAmAbstract");
     }
+    
     private Method iAmNotAbstract() throws NoSuchMethodException {
         abstract class TheNotAbstract {
             void iAmNotAbstract() {};
diff --git a/src/test/java/org/mockitousage/IMethods.java b/src/test/java/org/mockitousage/IMethods.java
index 15971a546b..f360475bec 100644
--- a/src/test/java/org/mockitousage/IMethods.java
+++ b/src/test/java/org/mockitousage/IMethods.java
@@ -187,6 +187,8 @@ public interface IMethods {
     String toString(String foo);
 
     void voidMethod();
+    
+    Void voidReturningMethod();
 
     String forList(List<String> list);
 
diff --git a/src/test/java/org/mockitousage/MethodsImpl.java b/src/test/java/org/mockitousage/MethodsImpl.java
index 1470b8dc87..b9830579e7 100644
--- a/src/test/java/org/mockitousage/MethodsImpl.java
+++ b/src/test/java/org/mockitousage/MethodsImpl.java
@@ -446,4 +446,9 @@ public Integer toIntWrapper(int i) {
     public String forObject(Object object) {
         return null;
     }
+
+    @Override
+    public Void voidReturningMethod() {
+        return null;
+    }
 }
diff --git a/src/test/java/org/mockitoutil/TestBase.java b/src/test/java/org/mockitoutil/TestBase.java
index 0488532c19..464e2d5840 100644
--- a/src/test/java/org/mockitoutil/TestBase.java
+++ b/src/test/java/org/mockitoutil/TestBase.java
@@ -56,7 +56,7 @@ public void resetState() {
         new StateMaster().reset();
     }
 
-    protected Invocation getLastInvocation() {
+    public static Invocation getLastInvocation() {
         return new MockitoCore().getLastInvocation();
     }