From d9bdfe680ad2e61b3d8d9a697531b5e05793b782 Mon Sep 17 00:00:00 2001 From: Matthew Ouyang Date: Mon, 31 Dec 2018 17:42:21 -0500 Subject: [PATCH] Fixes #1578: append mocks to existing MockitoSession - Problem - JUnitRule detects an unfinished mocking session when the apply method is invoked more than once. This commonly happens with Runners that enable developers to write nested test classes. - Fix - If a MockitoSession has been established for JUnitRule, then use that and initialize any new mocks (typically from a nested test class). - Test - Instantiate one @Rule and assign it to a second one. This will simulate the apply method being invoked more than once without introducing a new test dependency. --- .../org/mockito/internal/junit/JUnitRule.java | 17 +++++++++++------ .../junitrule/MockitoJUnitRuleTest.java | 4 ++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/mockito/internal/junit/JUnitRule.java b/src/main/java/org/mockito/internal/junit/JUnitRule.java index ba00c343ae..3bd3dacfe0 100644 --- a/src/main/java/org/mockito/internal/junit/JUnitRule.java +++ b/src/main/java/org/mockito/internal/junit/JUnitRule.java @@ -7,6 +7,7 @@ import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.mockito.MockitoSession; import org.mockito.internal.session.MockitoSessionLoggerAdapter; import org.mockito.plugins.MockitoLogger; @@ -34,12 +35,16 @@ public JUnitRule(MockitoLogger logger, Strictness strictness) { public Statement apply(final Statement base, final FrameworkMethod method, final Object target) { return new Statement() { public void evaluate() throws Throwable { - session = Mockito.mockitoSession() - .name(target.getClass().getSimpleName() + "." + method.getName()) - .strictness(strictness) - .logger(new MockitoSessionLoggerAdapter(logger)) - .initMocks(target) - .startMocking(); + if (session == null) { + session = Mockito.mockitoSession() + .name(target.getClass().getSimpleName() + "." + method.getName()) + .strictness(strictness) + .logger(new MockitoSessionLoggerAdapter(logger)) + .initMocks(target) + .startMocking(); + } else { + MockitoAnnotations.initMocks(target); + } Throwable testFailure = evaluateSafely(base); session.finishMocking(testFailure); if (testFailure != null) { diff --git a/src/test/java/org/mockitousage/junitrule/MockitoJUnitRuleTest.java b/src/test/java/org/mockitousage/junitrule/MockitoJUnitRuleTest.java index dfec883488..3ea7adde3e 100644 --- a/src/test/java/org/mockitousage/junitrule/MockitoJUnitRuleTest.java +++ b/src/test/java/org/mockitousage/junitrule/MockitoJUnitRuleTest.java @@ -19,6 +19,10 @@ public class MockitoJUnitRuleTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + // Fixes #1578: Protect against multiple execution. + @Rule + public MockitoRule mockitoRule2 = mockitoRule; + @Mock private Injected injected;