diff --git a/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java b/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java index 17b967efcf..e58659a166 100644 --- a/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java +++ b/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java @@ -107,18 +107,25 @@ public Object handle(Invocation invocation) throws Throwable { mockingProgress().reportOngoingStubbing(ongoingStubbing); } } else { - Object ret = mockSettings.getDefaultAnswer().answer(invocation); - DefaultAnswerValidator.validateReturnValueFor(invocation, ret); - - // Mockito uses it to redo setting invocation for potential stubbing in case of partial - // mocks / spies. - // Without it, the real method inside 'when' might have delegated to other self method - // and overwrite the intended stubbed method with a different one. - // This means we would be stubbing a wrong method. - // Typically this would led to runtime exception that validates return type with stubbed - // method signature. - invocationContainer.resetInvocationForPotentialStubbing(invocationMatcher); - return ret; + try { + Object ret = mockSettings.getDefaultAnswer().answer(invocation); + DefaultAnswerValidator.validateReturnValueFor(invocation, ret); + + return ret; + } finally { + // Mockito uses it to redo setting invocation for potential stubbing in case of + // partial + // mocks / spies. + // Without it, the real method inside 'when' might have delegated to other self + // method + // and overwrite the intended stubbed method with a different one. + // This means we would be stubbing a wrong method. + // Typically this would led to runtime exception that validates return type with + // stubbed + // method signature. + invocationContainer.resetInvocationForPotentialStubbing(invocationMatcher); + mockingProgress().reportOngoingStubbing(ongoingStubbing); + } } } diff --git a/src/test/java/org/mockitousage/misuse/SpyStubbingMisuseTest.java b/src/test/java/org/mockitousage/spies/SpyAsDefaultMockUsageTest.java similarity index 61% rename from src/test/java/org/mockitousage/misuse/SpyStubbingMisuseTest.java rename to src/test/java/org/mockitousage/spies/SpyAsDefaultMockUsageTest.java index 9f0acfee4e..463b9370d7 100644 --- a/src/test/java/org/mockitousage/misuse/SpyStubbingMisuseTest.java +++ b/src/test/java/org/mockitousage/spies/SpyAsDefaultMockUsageTest.java @@ -2,16 +2,14 @@ * Copyright (c) 2007 Mockito contributors * This program is made available under the terms of the MIT License. */ -package org.mockitousage.misuse; +package org.mockitousage.spies; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; +import static org.junit.Assert.assertSame; import static org.mockito.Mockito.*; import org.junit.Test; -import org.mockito.exceptions.misusing.WrongTypeOfReturnValue; -public class SpyStubbingMisuseTest { +public class SpyAsDefaultMockUsageTest { @Test public void nestedWhenTest() { @@ -19,15 +17,8 @@ public void nestedWhenTest() { Sampler mpoo = mock(Sampler.class); Producer out = spy(new Producer(mfoo)); - try { - when(out.produce()).thenReturn(mpoo); - fail(); - } catch (WrongTypeOfReturnValue e) { - assertThat(e.getMessage()) - .contains("spy") - .contains("syntax") - .contains("doReturn|Throw"); - } + when(out.produce()).thenReturn(mpoo); + assertSame(mpoo, out.produce()); } public class Sample {} diff --git a/subprojects/inline/src/test/java/org/mockitoinline/bugs/OngoingStubShiftTest.java b/subprojects/inline/src/test/java/org/mockitoinline/bugs/OngoingStubShiftTest.java new file mode 100644 index 0000000000..47062fedfd --- /dev/null +++ b/subprojects/inline/src/test/java/org/mockitoinline/bugs/OngoingStubShiftTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2007 Mockito contributors + * This program is made available under the terms of the MIT License. + */ +package org.mockitoinline.bugs; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; +import org.mockito.MockedStatic; +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mockStatic; + +public class OngoingStubShiftTest { + + private static class StaticInt { + static int getInt() { + return 1; + } + } + + private static class StaticStr { + static String getStr() { + return Integer.toString(StaticInt.getInt()); + } + } + + @Test + public void keep_ongoing_stub_when_spy() { + try (MockedStatic mockInt = mockStatic(StaticInt.class); + MockedStatic mockStr = mockStatic(StaticStr.class, CALLS_REAL_METHODS)) { + + mockStr.when(StaticStr::getStr).thenReturn("1"); + assertEquals("1", StaticStr.getStr()); + } + } + + private static class StaticWithException { + static String getString() { + return Integer.toString(getInt()); + } + + static int getInt() { + throw new NullPointerException(); + } + } + + @Test + public void keep_ongoing_stub_when_exception() { + try (MockedStatic mock = mockStatic(StaticWithException.class, CALLS_REAL_METHODS)) { + mock.when(StaticWithException::getString).thenReturn("1"); + assertEquals("1", StaticWithException.getString()); + } + } +}