gpt4 book ai didi

java - Mockito 在 final方法中调用真实代码而不是抛出 MissingMethodInvocationException

转载 作者:行者123 更新时间:2023-11-28 20:23:38 25 4
gpt4 key购买 nike

在下面的代码中,我希望 given 将抛出 MissingMethodInvocationException,因为 foo() 是最终的。

但是我在 str.equals("String 1") 得到了 NullPointerException
因此,Mockito 正在调用真实代码。为什么?

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());
}
}

在下面的示例中,我删除了 if 子句。现在它按预期工作。
当然,我不想删除这些行,因为我正在测试的代码需要它们。
这些线条的存在如何影响 Mockito 的行为?

    public final String foo() {
return str;
}

我如何确保 Mockito 永远不会调用方法上的真实代码,即使它们恰好是最终的?
我宁愿看到 MissingMethodInvocationException

在这段代码中,测试通过了:

    public String foo() {
if (str.equals("String 1")) {
str = "String 2";
}
return str;
}

我问的原因是我有一个测试用例,有人向正在测试/模拟的方法之一添加了 final 修饰符。
我们没有看到 MissingMethodInvocationException,而是看到了从模拟方法中的“真实”代码抛出的一些不相关的异常。我们花了一些时间寻找导致测试失败的地方和变化。
如果 Mockito 抛出 MissingMethodInvocationException,我们会立即看到原因。

最佳答案

tl;dr:Mockito 无法模拟 final 方法。而且它也无法检测到正在调用的 final方法。

更长的解释:这是 Java 中 final 的缺点之一。您唯一的选择是使用 Powermock,尽管我会保留对遗留代码的使用。

Mockito 的特点是它通过子类化类型来模拟,而 Java 编译器或 JVM 不允许任何子类化最终类或重写 final方法。 Mockito 不能用我们当前的设计做任何事情。

而漂亮的 Powermock 添加了另一个步骤,即在另一个类加载器中重新加载类,执行一些修改,尤其是删除要模拟的类型中的最终标志。尽管这种方法也有缺点:测试中的配置更多,测试消耗的 Permgen 明显更多,测试启动速度更慢。

关于java - Mockito 在 final方法中调用真实代码而不是抛出 MissingMethodInvocationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24571992/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com