Skip to content

Commit

Permalink
Fix mockito#2616 wrong stub for nested static
Browse files Browse the repository at this point in the history
  • Loading branch information
fishautumn committed Jun 14, 2022
1 parent ec27830 commit b62c317
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 12 deletions.
31 changes: 19 additions & 12 deletions src/main/java/org/mockito/internal/handler/MockHandlerImpl.java
Expand Up @@ -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);
}
}
}

Expand Down
@@ -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<StaticInt> mockInt = mockStatic(StaticInt.class);
MockedStatic<StaticStr> mockStr = mockStatic(StaticStr.class, CALLS_REAL_METHODS)) {

mockStr.when(StaticStr::getStr).thenReturn("1");
assertEquals("1", StaticStr.getStr());
}
}

private static class StaticWithException {
static int outer() {
return inner() + 1;
}

static int inner() {
throw new NullPointerException();
}
}

@Test
public void keep_ongoing_stub_when_exception() {
try (MockedStatic<StaticWithException> mock = mockStatic(StaticWithException.class, CALLS_REAL_METHODS)) {
mock.when(StaticWithException::outer).thenReturn(1);
assertEquals(1, StaticWithException.outer());
}
}
}

0 comments on commit b62c317

Please sign in to comment.