From 0b0a7ccbc5fdde33fc3f963367fdb1b814880e69 Mon Sep 17 00:00:00 2001 From: yushouqiu Date: Tue, 14 Jun 2022 16:13:15 +0800 Subject: [PATCH 1/2] Fix #2616 wrong stub for nested static --- .../internal/handler/MockHandlerImpl.java | 31 ++++++----- .../bugs/OngoingStubShiftTest.java | 54 +++++++++++++++++++ 2 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 subprojects/inline/src/test/java/org/mockitoinline/bugs/OngoingStubShiftTest.java 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/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()); + } + } +} From 81668d4950f2c907e9c40cfd1910f9643941ccfa Mon Sep 17 00:00:00 2001 From: yushouqiu Date: Wed, 15 Jun 2022 11:28:09 +0800 Subject: [PATCH 2/2] test: move SpyStubbingMisuse to SpyAsDefaultMockUsage as it becomes successful --- .../SpyAsDefaultMockUsageTest.java} | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) rename src/test/java/org/mockitousage/{misuse/SpyStubbingMisuseTest.java => spies/SpyAsDefaultMockUsageTest.java} (61%) 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 {}