Repository: mockito/mockito
Issue: Improve BaseStubbing & ThrowsException internals

I'd discovered some exception-stubbing related code that may express its intent more clearly during #1322 investigation.

Please see the PR for more details: #1324 

Issue comments:

Pull request review comments:
This is the current behavior, correct? E.g. your PR did not change it?
This comment explains what the code does but does not explain why (which is the point of code comments). Unfortunately, I don't know either :) I think it was a judgement call years ago and we will stick to it to keep compatibility. Thank you for cleaning up the TODO and adding test coverage.
This looks like a change in behavior. What is driving this? We are very careful when making changes in behavior that can cause issues when migrating to newer version of Mockito.
Thanks!
This exception message is not consistent with how we handle exceptions. Take a look at a Reporter class. Typically we throw an exception that is or derives from MockitoException. The message needs to be very clean, actionable to the end user. I suggest to create a high level unit test that demonstrates this use case from the standpoint of the end user. Run this test, observe the exception, would a newbie Mockito understand the exception message and was able to resolve the problem quickly?
I see, thank you! Now I think the TODO was added because it's strange when a _user_ passes a null varargs argument:
```java
thenReturn("foo", (String []) null);
// instead of 
thenReturn("foo", (String) null);
```
If that null array comes from somewhere else (e.g., a method `nextInvocationsArguments`), that almost always a programming error that must be fixed (we can't say if a user really means `{ null }`, or `{}`, or if that's an error).

Will Mockito stick with this decision in 2.x only, or in 3+ too? Will you consider changing that in the next releases? In the latter case I'd keep a TODO, but expand it with explanation _and_ a reference to an issue.
This one is tricky, as it must not occur because of an _external_ precondition that _Mockito_ first validates this answer. If this precondition is met (i.e., Mockito never calls `answer` if `validateFor` fails), it will never fire. Therefore, I can't think of how to yield this exception through _public_ API.

I've checked on 2.x with the following test, `answer` throws an NPE:

```java
    @Test
    public void should_not_answer_null_throwable() throws Throwable {
        try {
            // Shall #validateFor first!
            new ThrowsException(null).answer(new InvocationBuilder().toInvocation());
            Assertions.fail("Should have raised NPE");
        } catch (NullPointerException expected) {}
    }
```

I see such alternatives:
1. Keep an implicit null check. I believe it's not OK because this check is performed on the object state, and not on a user-supplied argument.
2. Add an explicit null check, throw NPE with description.
3. Add an explicit null check, throw IllegalStateException with description.
4. Add an explicit null check, report in a more user-friendly format.
5. Add a `validateFor` check in `answer`. It will _definetely_ catch when validateFor isn't called, but is redundant in case when Mockito always validates this answer (= adheres to the Answer+ValidableAnswer contract).

I'd say (5) is the safest one, but you make the same check twice (externally in the framework code + internally in the class itself). I can't say how expensive that is, or shall we trust the rest of the framework here, what do you think?

It seems `Reporter` is used to supply user-facing exceptions, but this one shall never occur in correct Mockito implementation. How do you report _internal_ errors?
Exactly, I've added to confirm that.
I considered how to clarify that in the case when any argument is null, we abort the stubbing.

It doesn't change _observable_ behavior, because `thenThrow(Class<? extends Throwable> throwableType)` does the same if null is passed (that was extracted in `abortNullExceptionType`).

If any code is added in `thenThrow(Class<? extends Throwable> throwableType)` _[before](https://github.com/mockito/mockito/pull/1324/files/84332358ad08f225c9bb293e5200792046d57ed7#diff-01345510e64bc217eb06fbf16e77739dR58)_ a null check, the behavior will become different.

If you think it's worth it, I'd do the same to  [`thenThrow(Throwable.. throwables)`](https://github.com/mockito/mockito/pull/1324/files/84332358ad08f225c9bb293e5200792046d57ed7#diff-01345510e64bc217eb06fbf16e77739dR43).
Unless there is a strong reason not to, I plan to keep the code as is. Nobody complained about it. There is risk that the change will be incompatible. It's better to focus Mockito 3 on more interesting features!

Thank you for pointing this out and attempting to clear up the TODO!
Oh I see now, thank you for clarification!

I don't see the value of this change. We are adding one extra method and creating small code duplication.
Oh, you're right, the user will never see it when using the public API. I missed that.

If this is only internal, IllegalStateException is perfect.
I'd rather keep the assignment for backwards compatibility. I made this change and will push it back to your pull request. Can you contribute a test that preserves this behavior?
Can you contribute a fix that makes it fail early when null passed via constructor? This would be cleaner (earlier feedback).
Oh, that's unexpected, thank you for adding a clarifying comment!

I think I'll add a couple of tests:
- The one that prevents the change I did.
- The one that verifies we get the throwable returned from `fillInStackTrace` in subsequent invocations.
What's interesting is that the custom exception from #866 breaks the [Throwable#fillInStackTrace contract](https://docs.oracle.com/javase/9/docs/api/java/lang/Throwable.html#fillInStackTrace--): this method shall always return `this`, never `null` or a reference to another throwable.

I actually did it locally earlier, and got failures in some integration tests. It seems the constructor has to allow null throwable so that we don't get UnfinishedStubbingException (I certainly can't say if that shall or can be fixed). Here is an example of failing test output:
```
org.mockitousage.stubbing.StubbingWithThrowablesTest > shouldNotAllowSettingNullThrowable FAILED
    java.lang.AssertionError: 
    Expected: (an instance of org.mockito.exceptions.base.MockitoException and exception with message a string containing "Cannot stub with null throwable")
         but: an instance of org.mockito.exceptions.base.MockitoException <org.junit.internal.runners.model.MultipleFailureException: There were 2 errors:
      org.mockito.exceptions.base.MockitoException(
    Cannot stub with null throwable!)
      org.mockito.exceptions.misusing.UnfinishedStubbingException(
    Unfinished stubbing detected here:
    -> at org.mockitousage.stubbing.StubbingWithThrowablesTest.shouldNotAllowSettingNullThrowable(StubbingWithThrowablesTest.java:154)

    E.g. thenReturn() may be missing.
    Examples of correct stubbing:
        when(mock.isOk()).thenReturn(true);
        when(mock.isOk()).thenThrow(exception);
        doThrow(exception).when(mock).someVoidMethod();
    Hints:
     1. missing thenReturn()
     2. you are trying to stub a final method, which is not supported
     3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
    )> is a org.junit.internal.runners.model.MultipleFailureException
    Stacktrace was: org.junit.internal.runners.model.MultipleFailureException: There were 2 errors:
      org.mockito.exceptions.base.MockitoException(
    Cannot stub with null throwable!)
      org.mockito.exceptions.misusing.UnfinishedStubbingException(
    Unfinished stubbing detected here:
    -> at org.mockitousage.stubbing.StubbingWithThrowablesTest.shouldNotAllowSettingNullThrowable(StubbingWithThrowablesTest.java:154)

    E.g. thenReturn() may be missing.
    Examples of correct stubbing:
        when(mock.isOk()).thenReturn(true);
        when(mock.isOk()).thenThrow(exception);
        doThrow(exception).when(mock).someVoidMethod();
    Hints:
     1. missing thenReturn()
     2. you are trying to stub a final method, which is not supported
     3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
    )
        at org.junit.runners.model.MultipleFailureException.assertEmpty(MultipleFailureException.java:67)
        at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:39)
        at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
        at org.junit.rules.RunRules.evaluate(RunRules.java:20)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
        at sun.reflect.GeneratedMethodAccessor60.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at com.sun.proxy.$Proxy1.processTestClass(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:108)
        at sun.reflect.GeneratedMethodAccessor59.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
        at java.lang.Thread.run(Thread.java:748)

```
Isn't it already tested in NPEWhenCustomExceptionStackTraceReturnNullTest?
I like this test. Can you check if we have top level integration tests for those use cases? I did a quick search and I think we have some gaps.

I'm wondering if top level tests under 'org.mockitousage.*' packages aren't better to verify and document this behavior. ThrowsExceptionTest is becoming big and complicated and it does seem to repeat the coverage of the other tests. Thoughts?
It is, shall I remove this unit test or expand the IT in `NPEWhenCustomExceptionStackTraceReturnNullTest`?
There is a similar integration test: `org.mockitousage.stubbing.StubbingConsecutiveAnswersTest#should_throw_consecutively`

Shall I remove this one?
As this test passed, the code 
```
throwable.fillInStackTrace();
filter.filter(throwable);
throw throwable;
```
didn't break #866 , did it?
Shan't we add a comment that these implementations of `fillInStackTrace` are totally incorrect -- they violate the method contract? Any Throwable implementation must always return a reference to `this` from `fillInStackTrace`.
Go ahead! I wanted to preserve current behavior in a test.
Why `linkplain` here instead of `link`?

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java b/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java
index ddb9a8dcb9..6dd99cd802 100644
--- a/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java
+++ b/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java
@@ -24,7 +24,8 @@ public OngoingStubbing<T> thenReturn(T value) {
     public OngoingStubbing<T> thenReturn(T value, T... values) {
         OngoingStubbing<T> stubbing = thenReturn(value);
         if (values == null) {
-            // TODO below does not seem right
+            // For no good reason we're configuring null answer here
+            // This has been like that since forever, so let's keep it for compatibility (unless users complain)
             return stubbing.thenReturn(null);
         }
         for (T v : values) {
@@ -65,7 +66,7 @@ public OngoingStubbing<T> thenThrow(Class<? extends Throwable> throwableType) {
     @Override
     public OngoingStubbing<T> thenThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown) {
         if (nextToBeThrown == null) {
-            thenThrow((Class<Throwable>) null);
+            return thenThrow((Class<Throwable>) null);
         }
         OngoingStubbing<T> stubbing = thenThrow(toBeThrown);
         for (Class<? extends Throwable> t : nextToBeThrown) {
diff --git a/src/main/java/org/mockito/internal/stubbing/StubberImpl.java b/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
index b18d05dae1..7771c0438f 100644
--- a/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
+++ b/src/main/java/org/mockito/internal/stubbing/StubberImpl.java
@@ -83,9 +83,9 @@ public Stubber doThrow(Class<? extends Throwable> toBeThrown) {
         Throwable e;
         try {
             e = newInstance(toBeThrown);
-        } catch (RuntimeException instanciationError) {
+        } catch (RuntimeException instantiationError) {
             mockingProgress().reset();
-            throw instanciationError;
+            throw instantiationError;
         }
         return doThrow(e);
     }
diff --git a/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java b/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java
index 037520fee3..502e359e00 100644
--- a/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java
+++ b/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java
@@ -14,23 +14,36 @@
 import static org.mockito.internal.exceptions.Reporter.cannotStubWithNullThrowable;
 import static org.mockito.internal.exceptions.Reporter.checkedExceptionInvalid;
 
+/**
+ * An answer that always throws the same throwable.
+ */
 public class ThrowsException implements Answer<Object>, ValidableAnswer, Serializable {
 
     private static final long serialVersionUID = 1128820328555183980L;
     private final Throwable throwable;
     private final ConditionalStackTraceFilter filter = new ConditionalStackTraceFilter();
 
+    /**
+     * Creates a new answer always throwing the given throwable. If it is null,
+     * {@linkplain ValidableAnswer#validateFor(InvocationOnMock) answer validation}
+     * will fail.
+     */
     public ThrowsException(Throwable throwable) {
         this.throwable = throwable;
     }
 
     public Object answer(InvocationOnMock invocation) throws Throwable {
+        if (throwable == null) {
+            throw new IllegalStateException("throwable is null: " +
+                "you shall not call #answer if #validateFor fails!");
+        }
         if (MockUtil.isMock(throwable)) {
             throw throwable;
         }
         Throwable t = throwable.fillInStackTrace();
 
         if (t == null) {
+            //Custom exceptions sometimes return null, see #866
             throw throwable;
         }
         filter.filter(t);


Test patch:
diff --git a/src/test/java/org/mockito/internal/stubbing/answers/ThrowsExceptionTest.java b/src/test/java/org/mockito/internal/stubbing/answers/ThrowsExceptionTest.java
index 8b553aae98..2e71102aaf 100644
--- a/src/test/java/org/mockito/internal/stubbing/answers/ThrowsExceptionTest.java
+++ b/src/test/java/org/mockito/internal/stubbing/answers/ThrowsExceptionTest.java
@@ -10,7 +10,9 @@
 import org.junit.Test;
 import org.mockito.exceptions.base.MockitoException;
 import org.mockito.internal.invocation.InvocationBuilder;
+import org.mockito.invocation.Invocation;
 
+import static junit.framework.TestCase.fail;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 
@@ -19,7 +21,7 @@ public class ThrowsExceptionTest {
     @Test
     public void should_raise_wanted_throwable() throws Throwable {
         try {
-            new ThrowsException(new IllegalStateException("my dear throwable")).answer(new InvocationBuilder().method("canThrowException").toInvocation());
+            new ThrowsException(new IllegalStateException("my dear throwable")).answer(createMethodInvocation());
             Assertions.fail("should have raised wanted exception");
         } catch (Throwable throwable) {
             assertThat(throwable).isInstanceOf(IllegalStateException.class).hasMessage("my dear throwable");
@@ -29,7 +31,7 @@ public void should_raise_wanted_throwable() throws Throwable {
     @Test
     public void should_throw_mock_exception_without_stacktrace() throws Exception {
         try {
-            new ThrowsException(mock(Exception.class)).answer(new InvocationBuilder().method("canThrowException").toInvocation());
+            new ThrowsException(mock(Exception.class)).answer(createMethodInvocation());
             Assertions.fail("should have raised wanted exception");
         } catch (Throwable throwable) {
             assertThat(throwable.getStackTrace()).describedAs("no stack trace, it's mock").isNull();
@@ -46,7 +48,7 @@ public void should_fill_in_exception_stacktrace() throws Exception {
         try {
 
             // when
-            new ThrowsException(throwableToRaise).answer(new InvocationBuilder().method("canThrowException").toInvocation());
+            new ThrowsException(throwableToRaise).answer(createMethodInvocation());
             Assertions.fail("should have raised wanted exception");
         } catch (Throwable throwable) {
             // then
@@ -59,24 +61,42 @@ public void should_fill_in_exception_stacktrace() throws Exception {
     @Test
     public void should_invalidate_null_throwable() throws Throwable {
         try {
-            new ThrowsException(null).validateFor(new InvocationBuilder().toInvocation());
+            Invocation invocation = createMethodInvocation();
+            new ThrowsException(null).validateFor(invocation);
             Assertions.fail("should have raised a MockitoException");
         } catch (MockitoException expected) {}
     }
 
+    @Test
+    public void should_throw_illegal_state_exception_if_null_answer() throws Throwable {
+        Invocation invocation = createMethodInvocation();
+        try {
+            new ThrowsException(null).answer(invocation);
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
     @Test
     public void should_pass_proper_checked_exception() throws Throwable {
-        new ThrowsException(new CharacterCodingException()).validateFor(new InvocationBuilder().method("canThrowException").toInvocation());
+        new ThrowsException(new CharacterCodingException()).validateFor(createMethodInvocation());
     }
 
     @Test(expected = MockitoException.class)
     public void should_fail_invalid_checked_exception() throws Throwable {
-        new ThrowsException(new IOException()).validateFor(new InvocationBuilder().method("canThrowException").toInvocation());
+        new ThrowsException(new IOException()).validateFor(createMethodInvocation());
     }
 
     @Test
     public void should_pass_RuntimeExceptions() throws Throwable {
-        new ThrowsException(new Error()).validateFor(new InvocationBuilder().method("canThrowException").toInvocation());
-        new ThrowsException(new RuntimeException()).validateFor(new InvocationBuilder().method("canThrowException").toInvocation());
+        new ThrowsException(new Error()).validateFor(createMethodInvocation());
+        new ThrowsException(new RuntimeException()).validateFor(createMethodInvocation());
+    }
+
+    /** Creates Invocation of a "canThrowException" method call. */
+    private static Invocation createMethodInvocation() {
+        return new InvocationBuilder()
+            .method("canThrowException")
+            .toInvocation();
     }
 }
diff --git a/src/test/java/org/mockitousage/bugs/FillInStackTraceScenariosTest.java b/src/test/java/org/mockitousage/bugs/FillInStackTraceScenariosTest.java
new file mode 100644
index 0000000000..5e3193e9ab
--- /dev/null
+++ b/src/test/java/org/mockitousage/bugs/FillInStackTraceScenariosTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.mockitousage.bugs;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockitousage.IMethods;
+import org.mockitoutil.TestBase;
+
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.when;
+
+/**
+ * These tests check that ThrowsException#answer throws an instance returned
+ * by Throwable#fillInStackTrace of the provided throwable.
+ *
+ * <p>A well-behaved Throwable implementation must always return a reference to this
+ * from #fillInStackTrace according to the method contract.
+ * However, Mockito throws the exception returned from #fillInStackTrace for backwards compatibility
+ * (or the provided exception if the method returns null).
+ *
+ * @see Throwable#fillInStackTrace()
+ * @see <a href="https://github.com/mockito/mockito/issues/866">#866</a>
+ */
+public class FillInStackTraceScenariosTest extends TestBase {
+
+    @Mock IMethods mock;
+
+    private class SomeException extends RuntimeException {}
+
+    class NullStackTraceException extends RuntimeException {
+        public Exception fillInStackTrace() {
+            return null;
+        }
+    }
+
+    class NewStackTraceException extends RuntimeException {
+        public Exception fillInStackTrace() {
+            return new SomeException();
+        }
+    }
+
+    //issue 866
+    @Test
+    public void avoids_NPE() {
+        when(mock.simpleMethod()).thenThrow(new NullStackTraceException());
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch(NullStackTraceException e) {}
+    }
+
+    @Test
+    public void uses_return_value_from_fillInStackTrace() {
+        when(mock.simpleMethod()).thenThrow(new NewStackTraceException());
+        try {
+            mock.simpleMethod();
+            fail();
+        } catch(SomeException e) {}
+    }
+}
diff --git a/src/test/java/org/mockitousage/bugs/NPEWhenCustomExceptionStackTraceReturnNullTest.java b/src/test/java/org/mockitousage/bugs/NPEWhenCustomExceptionStackTraceReturnNullTest.java
deleted file mode 100644
index 92a130528a..0000000000
--- a/src/test/java/org/mockitousage/bugs/NPEWhenCustomExceptionStackTraceReturnNullTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2017 Mockito contributors
- * This program is made available under the terms of the MIT License.
- */
-package org.mockitousage.bugs;
-
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockitousage.IMethods;
-import org.mockitoutil.TestBase;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.when;
-
-public class NPEWhenCustomExceptionStackTraceReturnNullTest extends TestBase {
-
-    @Mock
-    IMethods mock;
-
-    class NullStackTraceException extends RuntimeException {
-        @Override
-        public Exception fillInStackTrace() {
-            return null;
-        }
-    }
-
-    //issue 866
-    @Test
-    public void shouldNotThrowNPE() {
-        when(mock.simpleMethod()).thenThrow(new NullStackTraceException());
-        try {
-            mock.simpleMethod();
-            fail();
-        } catch(NullStackTraceException e) {}
-    }
-}
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingConsecutiveAnswersTest.java b/src/test/java/org/mockitousage/stubbing/StubbingConsecutiveAnswersTest.java
index f8fa2b536e..47c217280e 100644
--- a/src/test/java/org/mockitousage/stubbing/StubbingConsecutiveAnswersTest.java
+++ b/src/test/java/org/mockitousage/stubbing/StubbingConsecutiveAnswersTest.java
@@ -41,6 +41,34 @@ public void should_return_consecutive_values_for_two_nulls() throws Exception {
         assertNull(mock.simpleMethod());
     }
 
+    @Test
+    public void should_return_consecutive_values_first_var_arg_null() throws Exception {
+        when(mock.simpleMethod()).thenReturn("one", (String) null);
+
+        assertEquals("one", mock.simpleMethod());
+        assertNull(mock.simpleMethod());
+        assertNull(mock.simpleMethod());
+    }
+
+    @Test
+    public void should_return_consecutive_values_var_arg_null() throws Exception {
+        when(mock.simpleMethod()).thenReturn("one", (String[]) null);
+
+        assertEquals("one", mock.simpleMethod());
+        assertNull(mock.simpleMethod());
+        assertNull(mock.simpleMethod());
+    }
+
+    @Test
+    public void should_return_consecutive_values_var_args_contain_null() throws Exception {
+        when(mock.simpleMethod()).thenReturn("one", "two", null);
+
+        assertEquals("one", mock.simpleMethod());
+        assertEquals("two", mock.simpleMethod());
+        assertNull(mock.simpleMethod());
+        assertNull(mock.simpleMethod());
+    }
+
     @Test
     public void should_return_consecutive_values_set_by_shorten_then_return_method() throws Exception {
         when(mock.simpleMethod()).thenReturn("one", "two", "three");
diff --git a/src/test/java/org/mockitousage/stubbing/StubbingWithThrowablesTest.java b/src/test/java/org/mockitousage/stubbing/StubbingWithThrowablesTest.java
index 9f526bfc63..935372426a 100644
--- a/src/test/java/org/mockitousage/stubbing/StubbingWithThrowablesTest.java
+++ b/src/test/java/org/mockitousage/stubbing/StubbingWithThrowablesTest.java
@@ -22,6 +22,9 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Map;
+
+import org.assertj.core.api.Assertions;
+import org.assertj.core.api.ThrowableAssert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -48,6 +51,48 @@ public void setup() {
         mockTwo = mock(HashMap.class);
     }
 
+    @Test
+    public void throws_same_exception_consecutively() {
+        when(mock.add("")).thenThrow(new ExceptionOne());
+
+        //1st invocation
+        Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
+            public void call() {
+                mock.add("");
+            }
+        }).isInstanceOf(ExceptionOne.class);
+
+        mock.add("1");
+
+        //2nd invocation
+        Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
+            public void call() {
+                mock.add("");
+            }
+        }).isInstanceOf(ExceptionOne.class);
+    }
+
+    @Test
+    public void throws_same_exception_consecutively_with_doThrow() {
+        doThrow(new ExceptionOne()).when(mock).clear();
+
+        //1st invocation
+        Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
+            public void call() {
+                mock.clear();
+            }
+        }).isInstanceOf(ExceptionOne.class);
+
+        mock.add("1");
+
+        //2nd invocation
+        Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
+            public void call() {
+                mock.clear();
+            }
+        }).isInstanceOf(ExceptionOne.class);
+    }
+
     @Test
     public void shouldStubWithThrowable() throws Exception {
         IllegalArgumentException expected = new IllegalArgumentException("thrown by mock");
@@ -55,7 +100,6 @@ public void shouldStubWithThrowable() throws Exception {
 
         exception.expect(sameInstance(expected));
         mock.add("throw");
-
     }
 
     @Test