[英]Final method mocking
我需要使用 mockito 的最终方法模拟一些 class。我写了这样的东西
@Test
public void test() {
B b = mock(B.class);
doReturn("bar called").when(b).bar();
assertEquals("must be \"overrided\"", "bar called", b.bar());
//bla-bla
}
class B {
public final String bar() {
return "fail";
}
}
但它失败了。 我尝试了一些“破解”并且它有效。
@Test
public void hackTest() {
class NewB extends B {
public String barForTest() {
return bar();
}
}
NewB b = mock(NewB.class);
doReturn("bar called").when(b).barForTest();
assertEquals("must be \"overrided\"", "bar called", b.barForTest());
}
它有效,但“闻起来”。
那么,正确的方法在哪里呢?
谢谢。
在 Mockito 中不支持模拟最终方法。
正如 Jon Skeet 评论的那样,您应该寻找一种方法来避免对 final 方法的依赖。 也就是说,有一些方法可以通过字节码操作(例如使用 PowerMock)
Mockito 和 PowerMock 之间的比较将详细说明事情。
Mockito 的局限性是什么
- 不能模拟最终方法——它们的真实行为无一例外地被执行。 Mockito 无法警告您模拟 final 方法,因此请保持警惕。
您可以将 Powermock 与 Mockito 一起使用,然后您不需要继承 B.class。 只需将其添加到测试类的顶部
@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)
@PrepareForTest
指示 Powermock 检测 B.class 以使 final 和 static 方法可模拟。 这种方法的一个缺点是您必须使用 PowerMockRunner,这会阻止使用其他测试运行器,例如 Spring 测试运行器。
Mockito 2 现在支持模拟 final 方法,但这是一个“孵化”功能。 它需要一些步骤来激活它,如下所述: https : //github.com/mockito/mockito/wiki/What's-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-最终类方法
Mockito 2.x 现在支持 final 方法和 final 类存根。
从文档:
最终类和方法的模拟是一个孵化、选择加入的特性。 必须通过创建包含一行的文件
src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
来显式激活此功能:
mock-maker-inline
创建此文件后,您可以执行以下操作:
final class FinalClass { final String finalMethod() { return "something"; } } FinalClass concrete = new FinalClass(); FinalClass mock = mock(FinalClass.class); given(mock.finalMethod()).willReturn("not anymore"); assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());
在随后的里程碑中,团队将带来使用此功能的程序化方式。 我们将为所有不可模拟的场景识别并提供支持。
假设B类如下:
class B {
private String barValue;
public final String bar() {
return barValue;
}
public void final setBar(String barValue) {
this.barValue = barValue;
}
}
有一种更好的方法可以在不使用 PowerMockito 框架的情况下做到这一点。 你可以为你的类创建一个 SPY 并且可以模拟你的 final 方法。 以下是执行此操作的方法:
@Test
public void test() {
B b = new B();
b.setBar("bar called") //This should the expected output:final_method_bar()
B spyB = Mockito.spy(b);
assertEquals("bar called", spyB.bar());
}
Mockito 可用于模拟最终类或最终方法。 问题是,这不是来自 Mockito 的开箱即用功能,需要明确配置。
所以,为了做到这一点,
在项目的src/test/resources/mockito-extensions
目录下创建一个名为org.mockito.plugins.MockMaker
的文本文件,并添加如下一行文本
mock-maker-inline
完成后,您可以使用 mockito 的when方法像任何其他常规方法一样模拟行为。
在此处查看详细示例
我只是做了同样的事情。 我的情况是我想确保该方法不会“导致”错误,但由于它是一个 catch/log/return 方法,我无法在不修改类的情况下直接测试它。
我想简单地模拟我传入的记录器,但是关于模拟“Log”接口的一些东西似乎不起作用,并且模拟像“SimpleLog”这样的类也不起作用,因为这些方法是最终的。
我最终创建了一个扩展 SimpleLog 的匿名内部类,它覆盖了其他人都委托给的基本级别的“log(level, string, error)”方法,然后只等待“级别”为 5 的调用。
一般来说,为行为扩展一个类并不是一个坏主意,如果不是太复杂的话,它可能比模拟更好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.