我也是Mockito和PowerMockito的新手。我发现我无法使用纯Mockito测试静态方法所以我需要使用PowerMockito(对吗?)。
我有一个非常简单的类,叫做Validate,这个方法非常简单
public class Validate {
public final static void stateNotNull(
final Object object,
final String message) {
if (message == null) {
throw new IllegalArgumentException("Exception message is a null object!");
}
if (object == null) {
throw new IllegalStateException(message);
}
}
所以我需要验证:
1)当我在空消息参数上调用静态方法时,IllegalArgumentException被称为
2)当我在null对象参数上调用静态方法时,调用IllegalStateException
从我到目前为止,我写了这个测试:
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.isNull;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.testng.annotations.Test;
@RunWith(PowerMockRunner.class)
@PrepareForTest(Validate.class)
public class ValidateTestCase {
@Test(expectedExceptions = { IllegalStateException.class })
public void stateNotNullTest() throws Exception {
PowerMockito.mockStatic(Validate.class);
Validate mock = PowerMockito.mock(Validate.class);
PowerMockito.doThrow(new IllegalStateException())
.when(mock)
.stateNotNull(isNull(), anyString());
Validate.stateNotNull(null, null);
}
}
所以这说我模拟了Validate类,我正在检查当使用null参数作为对象并且任何字符串作为消息调用该方法时,会抛出IllegalStateException。
现在,我真的不明白。为什么我不能直接调用那个方法,放弃整个伏都教魔法围绕模拟静态类?在我看来,除非我调用Validate.stateNotNull,否则测试通过......我应该为什么原因嘲笑它?
答案 0 :(得分:11)
您不应该模拟您正在测试的类和方法。您应该只模拟执行测试所需的方法。
例如,如果您需要Web服务中的某些对象来执行测试,则可以模拟Web服务调用,因此您无需实际调用Web服务。
答案 1 :(得分:8)
首先,确定您的目标是什么以及您想要测试什么。您的测试不是测试您的Validate类方法,而是创建一个行为类似于该方法的模拟,如Fortega points out。确定您正在测试的内容(测试中的对象)以及执行测试所需的内容(协作者),然后查看协作者并确定它们是否易于创建或是否需要嘲笑他们。
对于像这个没有任何依赖关系的类,我建议完全没有模拟。这里没有什么需要嘲笑,测试可以这样写:
import static org.junit.Assert.*;
public class ValidateTestCase {
@Test
public void testHappyPath() throws Exception {
Validate.stateNotNull("", "");
}
@Test
public void testNullMessage() throws Exception {
try {
Validate.stateNotNull(null, null);
fail();
}
catch (IllegalStateException e) {
String expected = "Exception message is a null object!"
assertEquals(expected, e.getMessage());
}
}
@Test(expected=IllegalStateException.class)
public void testNullObject() throws Exception {
Validate.stateNotNull(null, "test");
}
}
并告诉您代码是否符合您的要求。
除非存在一些您希望避免引入测试的依赖项,否则不要进行模拟,因为它是外部资源(如文件系统或数据库)或某些复杂的子系统。模拟框架可能非常有用,但它们会增加复杂性,它们可能会过度指定所测试事物的行为,使测试变得脆弱,并且可能使测试难以阅读。如果可以的话,没有它们。