Assuming I have the following classes
public class StaticClass {
public static void staticMethod() throws SomeException {
System.out.println("staticMethod");
}
private StaticClass() {
}
}
and
public class SomeClass {
public void someMethod() {
try {
StaticClass.staticMethod();
}catch(SomeException ex) {
System.out.println("SomeException occurred");
return;
}
System.out.println("SomeException didn't occur");
}
}
which I'm testing with
@RunWith(PowerMockRunner.class)
@PrepareForTest(StaticClass.class)
public class SomeClassTest {
@Test
public void testStaticMethod() throws Exception {
mockStatic(StaticClass.class);
doThrow(new SomeException("unimportant message")).when(StaticClass.class,
"staticMethod");
//test something where exception is needed
SomeClass instance = new SomeClass();
try {
instance.someMethod();
fail("IllegalStateException expected");
}catch(IllegalStateException expected) {
}
//now test something where exception isn't needed
instance.someMethod();
}
}
How can I undo the static mocking/the configuration to throw SomeException
so that I can test the code after the try-catch block in the second instance.someMethod()
?
PowerMock: How to unmock a method? doesn't apply because there's no mock reference to pass to Mockito.reset
and passing StaticClass
causes java.lang.ClassCastException: java.lang.Class cannot be cast to org.mockito.internal.creation.bytebuddy.MockAccess
.
SomeException
simply extends Exception
.
A SSCCE is provided at https://gitlab.com/krichter/powermock-undo-statik-mocking.
I'm using PowerMock 1.7.3.
My opinion, but in general a unit test should exercise a single code path. (I think of this as applying single responsibility to a test method.)
Bu my suggestion about splitting the tests does solve the problem. I don't know the details, but @PrepareForTest provides a fresh StaticClass for each test.
These separate tests work:
@Test
public void testStaticMethodWhenSomethingUnexpectedHappens() throws Exception {
mockStatic(StaticClass.class);
// changed exception type
doThrow(new IllegalStateException("unimportant message")).when(StaticClass.class, "staticMethod");
SomeClass instance = new SomeClass();
try {
instance.someMethod();
fail("IllegalStateException expected");
} catch (IllegalStateException expected) {
}
// added verification
verifyStaticMethodWasInvokedOneTime();
}
@Test
public void testStaticMethodHappyPath() throws Exception {
mockStatic(StaticClass.class);
doNothing().when(StaticClass.class, "staticMethod");
SomeClass instance = new SomeClass();
instance.someMethod();
// added verification
verifyStaticMethodWasInvokedOneTime();
}
private void verifyStaticMethodWasInvokedOneTime() throws SomeException {
verifyStatic(StaticClass.class);
StaticClass.staticMethod();
}