在下面的代码中,我希望given
将MissingMethodInvocationException
投放foo()
,因为NullPointerException
是最终的。
但我在str.equals("String 1")
得到import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
class Foo {
private String str = "String 1";
public final String foo() {
if (str.equals("String 1")) {
str = "String 2";
}
return str;
}
}
@RunWith(MockitoJUnitRunner.class)
public class TestClass {
@Mock
Foo foo;
@Test
public void test() {
given(foo.foo()).willReturn("x");
assertEquals("x", foo.foo());
}
}
所以,Mockito正在调用真正的代码。为什么呢?
public final String foo() {
return str;
}
在下面的示例中,我删除了if子句。现在它按预期工作。
当然,我不想删除那些在我测试的代码中需要的行。
这些线条的存在如何影响Mockito的行为?
MissingMethodInvocationException
我怎样才能确保Mockito永远不会在方法上调用真正的代码,即使它们恰好是最终的?
我宁愿看 public String foo() {
if (str.equals("String 1")) {
str = "String 2";
}
return str;
}
。
在此代码中,测试通过:
final
我问的原因是我有一个测试用例并且有人将MissingMethodInvocationException
修饰符添加到正在测试/模拟的方法之一。
我们没有看到MissingMethodInvocationException
,而是看到了一些与“真实”无关的例外情况。模拟方法中的代码。我们花了一些时间寻找导致测试失败的地方和变化
如果Mockito投掷{{1}},我们会立即看到原因。
答案 0 :(得分:3)
tl; dr :Mockito无法模拟最终方法。并且它无法检测到被调用的最终方法。
更长的解释:这是Java决赛的一个缺点。你唯一的选择是使用Powermock,尽管我会继续使用Powermock。
Mockito的作用是它通过将类型子类化为mock来工作,而Java编译器或JVM只是不允许任何子类化最终类或覆盖最终方法的东西。 Mockito对我们目前的设计无能为力。
而漂亮的Powermock又添加了另一个步骤,在另一个类加载器中重新加载类,执行多个修改,特别是删除类型中的最终标志以进行模拟。虽然这种方法也有缺点:测试中的配置越多,测试消耗的Permgen就越多,测试速度越慢。
答案 1 :(得分:0)