我正在尝试使用PowerMock,而不是Mockito;因为我喜欢用于whennew()和verifyprivate()的API,但是在尝试使用Junit中的类别TestRunner运行测试套件时遇到了一些问题。
为了使用默认的JUnit测试运行器,我创建了一个TestCase并添加了 PowerMockRule作为带有@Rule注释的实例字段。虽然执行测试的工作方式如此,但 ExpectedException TestRule在结合使用时不起作用
示例代码
@PowerMockIgnore ("*")
@PrepareForTest (CustomizedSSHConnection.class)
public class TestExpectedExceptionRule {
private Connection connection;
private ConnectionInfo connectionInfo;
@Rule
public PowerMockRule rule = new PowerMockRule ();
@Rule
public ExpectedException exception = ExpectedException.none ();
@Test
public void testExcepitonWithPowerMockRule() {
exception.expect (NullPointerException.class);
exception.expectMessage ("Image is null");
throw new NullPointerException ("Image is null");
}
}
如果我使用@RunWith(PowerMockRunner.class),而不是使用@Rule PowerMockRule,则此测试用例将通过。
另一个观察是,如果我使用@ClassRule注释PowerMockRule,这会成功但是一些模拟方法会抛出异常。
答案 0 :(得分:2)
PowerMock创建TestExpectedExceptionRule
对象的深层克隆。因此,它使用新的ExpectedException
规则运行测试,但您在原始规则上调用exception.expect (NullPointerException.class)
。因此测试失败,因为ExpectedException
规则的克隆不期望异常。
尽管如此,至少有两种解决方案可以解决您的问题。
使用JUnit的RuleChain
订购规则。这需要一些额外的丑陋代码,但它可以工作。
private ExpectedException exception = ExpectedException.none ();
private PowerMockRule powerMockRule = new PowerMockRule();
@Rule
public TestRule ruleChain = RuleChain.outerRule(new TestRule() {
@Override
public Statement apply(Statement base, Description description) {
return powerMockRule.apply(base, null, description);
}
}).around(exception);
如果您使用的是Java 8,则可以将ExpectedException
规则替换为Fishbowl库。
@Test
public void testExcepitonWithPowerMockRule() {
Throwable exception = exceptionThrownBy(
() -> throw new NullPointerException ("Image is null"));
assertEquals(NullPointerException.class, exception.getClass());
assertEquals("Image is null", exception.getMessage());
}
如果没有Java 8,则必须使用匿名类。
@Test
public void fooTest() {
Throwable exception = exceptionThrownBy(new Statement() {
public void evaluate() throws Throwable {
throw new NullPointerException ("Image is null");
}
});
assertEquals(NullPointerException.class, exception.getClass());
assertEquals("Image is null", exception.getMessage());
}
答案 1 :(得分:0)
我通过创建一个使用PowerMockTestUtil
的{{1}}类解决了这个问题。
实用程序类:
FunctionalInterface
样本测试:
/**
* Utility class to provide some testing functionality that doesn't play well with Powermock out
* of the box. For example, @Rule doesn't work well with Powermock.
*/
public class PowerMockTestUtil {
public static void expectException(RunnableWithExceptions function, Class expectedClass, String expectedMessage) {
try {
function.run();
fail("Test did not generate expected exception of type " + expectedClass.getSimpleName());
} catch (Exception e) {
assertTrue(e.getClass().isAssignableFrom(expectedClass));
assertEquals(expectedMessage, e.getMessage());
}
}
@FunctionalInterface
public interface RunnableWithExceptions<E extends Exception> {
void run() throws E;
}
}
答案 2 :(得分:-1)
我能够使用@Test
注释中的预期属性来修复此问题。但是这种方法的问题是我无法断言异常消息。这对我来说现在很好。
@PowerMockIgnore ("*")
@PrepareForTest (CustomizedSSHConnection.class)
public class TestExpectedExceptionRule {
private Connection connection;
private ConnectionInfo connectionInfo;
@Rule
public PowerMockRule rule = new PowerMockRule ();
@Rule
public ExpectedException exception = ExpectedException.none ();
@Test(expected = NullPointerException.class)
public void testExcepitonWithPowerMockRule() {
throw new NullPointerException ("Image is null");
}
}