Skip to content

Commit

Permalink
Fixes 976: Change to StackTraceCleaner to allow mockito strick stubs … (
Browse files Browse the repository at this point in the history
#977)

* Fixes 976: Change to StackTraceCleaner to allow mockito strick stubs mode to work correctly

* Fixes 976: Additional package prefix in StackTraceCleaner to cover JDK 9 internal relfection package
  • Loading branch information
stevegilbert23 authored and thekingn0thing committed Apr 21, 2019
1 parent 70fb673 commit 54f49a5
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ public StackTraceCleaner getStackTraceCleaner(final StackTraceCleaner defaultCle
return new StackTraceCleaner() {
@Override
public boolean isIn(StackTraceElement candidate) {
return defaultCleaner.isIn(candidate) && !candidate.getClassName().startsWith("org.powermock.api.mockito");
return defaultCleaner.isIn(candidate) && !candidate.getClassName().startsWith("org.powermock.")
&& !candidate.getClassName().startsWith("sun.reflect.")
&& !candidate.getClassName().startsWith("java.lang.reflect.")
&& !candidate.getClassName().startsWith("jdk.internal.reflect.")
&& candidate.getLineNumber() != -1;
}
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package samples.powermockito.junit4.stacktracecleaner;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.internal.stubbing.InvocationContainerImpl;
import org.mockito.internal.util.MockUtil;
import org.mockito.invocation.Location;
import org.mockito.invocation.MockHandler;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Stubbing;
import org.powermock.api.mockito.invocation.MockHandlerAdaptor;
import org.powermock.api.mockito.invocation.MockitoMethodInvocationControl;
import org.powermock.core.MockRepository;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.powermock.api.mockito.PowerMockito.doNothing;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;

/**
* Ensures Location.toString returns the location where a mock is declared. The filtering of the stack trace used
* to determine the location is performed by the StackTraceCleaner in StackTraceCleanerProvider.
*/
@RunWith(value = PowerMockRunner.class)
@PowerMockRunnerDelegate(MockitoJUnitRunner.StrictStubs.class)
@PrepareForTest({SomethingWithStaticMethod.class})
public class LocationFromStackTraceTest {
@Test
public void should_filter_extra_elements_in_stack_when_mocking_static_method() throws Exception {
mockStatic(SomethingWithStaticMethod.class);
when(SomethingWithStaticMethod.doStaticOne()).thenReturn("Something else 1");
when(SomethingWithStaticMethod.doStaticTwo()).thenReturn("Something else 2");
doNothing().when(SomethingWithStaticMethod.class, "doStaticVoid");

MockitoMethodInvocationControl invocationControl =
(MockitoMethodInvocationControl)
MockRepository.getStaticMethodInvocationControl(SomethingWithStaticMethod.class);
MockHandlerAdaptor mockHandlerAdaptor = invocationControl.getMockHandlerAdaptor();
Object mock = mockHandlerAdaptor.getMock();
MockHandler<Object> mockHandler = MockUtil.getMockHandler(mock);
InvocationContainerImpl invocationContainer = (InvocationContainerImpl)mockHandler.getInvocationContainer();
List<Stubbing> stubbings = new ArrayList<Stubbing>(invocationContainer.getStubbingsAscending());
assertThat(stubbings.size(), is(3));
Location static1Location = stubbings.get(0).getInvocation().getLocation();
assertThat(static1Location.toString(), is("-> at samples.powermockito.junit4.stacktracecleaner." +
"LocationFromStackTraceTest.should_filter_extra_elements_in_stack_when_mocking_static_method(" +
"LocationFromStackTraceTest.java:37)"));
Location static2Location = stubbings.get(1).getInvocation().getLocation();
assertThat(static2Location.toString(), is("-> at samples.powermockito.junit4.stacktracecleaner." +
"LocationFromStackTraceTest.should_filter_extra_elements_in_stack_when_mocking_static_method(" +
"LocationFromStackTraceTest.java:38)"));
Location staticVoidLocation = stubbings.get(2).getInvocation().getLocation();
assertThat(staticVoidLocation.toString(), is("-> at samples.powermockito.junit4.stacktracecleaner." +
"LocationFromStackTraceTest.should_filter_extra_elements_in_stack_when_mocking_static_method(" +
"LocationFromStackTraceTest.java:39)"));

// Removing these calls and the three Location assertions above will cause the test to fail due to the
// strict stubs. Without the alterations to StackTraceCleanerProvider, the failure messages will contain
// an item in the stack trace inside the powermock libraries.
assertThat(SomethingWithStaticMethod.doStaticOne(), is("Something else 1"));
assertThat(SomethingWithStaticMethod.doStaticTwo(), is("Something else 2"));
SomethingWithStaticMethod.doStaticVoid();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package samples.powermockito.junit4.stacktracecleaner;

public class SomethingWithStaticMethod {
public static String doStaticOne() {
return "I am static 1";
}

public static String doStaticTwo() {
return "I am static 2";
}

public static void doStaticVoid() {
}
}

0 comments on commit 54f49a5

Please sign in to comment.