Java 最终方法模拟
我需要用mockito的最终方法模拟一些类。我写过这样的东西Java 最终方法模拟,java,unit-testing,testing,mocking,mockito,Java,Unit Testing,Testing,Mocking,Mockito,我需要用mockito的最终方法模拟一些类。我写过这样的东西 @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(
@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中不支持模拟final方法 正如Jon Skeet所评论的,您应该寻找一种方法来避免对最终方法的依赖。也就是说,通过字节码操作(例如,使用PowerMock)有一些解决方法
A将详细解释事情。在Mockito中不支持模拟final方法 正如Jon Skeet所评论的,您应该寻找一种方法来避免对最终方法的依赖。也就是说,通过字节码操作(例如,使用PowerMock)有一些解决方法 A将详细解释事情。来自: Mockito的局限性是什么
- 无法模拟最终方法-它们的真实行为是毫无例外地执行的。Mockito无法警告您有关模拟最终方法的信息,因此请保持警惕
- 无法模拟最终方法-它们的真实行为是毫无例外地执行的。Mockito无法警告您有关模拟最终方法的信息,因此请保持警惕
您可以将Powermock与Mockito一起使用,这样就不需要子类B.class。只需将其添加到测试类的顶部
@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)
@PrepareForTest
指示Powermock对B.class进行指令,使final和static方法可模拟。这种方法的一个缺点是,您必须使用PowerMockRunner,这就排除了使用其他测试运行程序(如Spring测试运行程序)的可能性。您可以将Powermock与Mockito一起使用,那么您就不需要子类B.class。只需将其添加到测试类的顶部
@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)
@PrepareForTest
指示Powermock对B.class进行指令,使final和static方法可模拟。这种方法的一个缺点是必须使用PowerMockRunner,这就排除了使用其他测试运行程序,例如Spring测试运行程序。我刚才也做了同样的事情。我的情况是,我希望确保该方法不会“导致”错误,但由于它是catch/log/return方法,因此在不修改类的情况下,我无法直接测试它
我想简单地模拟我传入的记录器,但是关于模拟“Log”接口的东西似乎不起作用,而模拟“SimpleLog”之类的类也不起作用,因为这些方法是最终的
我最终创建了一个扩展SimpleLog的匿名内部类,该类重写了其他人都委托给的基级“log(level,string,error)”方法,然后等待一个“level”为5的调用
一般来说,为行为扩展类并不是一个坏主意,如果不是太复杂的话,可能比模仿更好。我也做了同样的事情。我的情况是,我希望确保该方法不会“导致”错误,但由于它是catch/log/return方法,因此在不修改类的情况下,我无法直接测试它 我想简单地模拟我传入的记录器,但是关于模拟“Log”接口的东西似乎不起作用,而模拟“SimpleLog”之类的类也不起作用,因为这些方法是最终的 我最终创建了一个扩展SimpleLog的匿名内部类,该类重写了其他人都委托给的基级“log(level,string,error)”方法,然后等待一个“level”为5的调用
一般来说,为行为扩展类并不是一个坏主意,如果不太复杂的话,可能比模拟更可取。Mockito 2现在支持模拟最终方法,但这是一个“孵化”功能。激活它需要一些步骤,如下所述:
Mockito 2现在支持模拟最终方法,但这是一个“孵化”功能。激活它需要一些步骤,如下所述:
假设B类如下:
class B {
private String barValue;
public final String bar() {
return barValue;
}
public void final setBar(String barValue) {
this.barValue = barValue;
}
}
有一种更好的方法可以做到这一点,而不用使用PowerMockito框架。
您可以为您的类创建一个间谍,并可以模拟您的最终方法。
以下是操作方法:
@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());
}
假设B类如下所示:
class B {
private String barValue;
public final String bar() {
return barValue;
}
public void final setBar(String barValue) {
this.barValue = barValue;
}
}
有一种更好的方法可以做到这一点,而不用使用PowerMockito框架。
您可以为您的类创建一个间谍,并可以模拟您的最终方法。
以下是操作方法:
@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());
}
Mockito2.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());
在随后的里程碑中,团队将提供使用此功能的编程方式。我们将确定并支持所有不可修改的场景
Mockito2.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());
在随后的里程碑中,团队将提供使用此功能的编程方式。我们将确定并支持所有不可修改的场景
当然,理想情况是不需要模仿最终的方法。你还没有告诉我们你为什么要这么做。我通常努力保持我对接口的依赖性。。。你有没有办法使用一个接口来代理真实的类(假设你不能更改类本身)?这个类来自一些遗留代码。你没有修改它的选项吗?或代理