最终方法嘲笑

Sta*_*lin 60 java testing unit-testing mocking mockito

我需要使用mockito使用final方法模拟一些类.我写过这样的东西

@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";
    }
}
Run Code Online (Sandbox Code Playgroud)

但它失败了.我尝试了一些"黑客",它的确有效.

   @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());
    }
Run Code Online (Sandbox Code Playgroud)

它有效,但"闻起来".

那么,正确的方式在哪里?

谢谢.

mat*_*t b 32

来自Mockito FAQ:

Mockito有什么限制

  • 无法模拟最终方法 - 它们的实际行为在没有任何异常的情况下执行.Mockito无法警告你嘲笑最终方法,所以请保持警惕.

  • 现在仅在 *Mockito 1.x 特定限制* https://github.com/mockito/mockito/wiki/FAQ#mockito-1x-specific-limitations 下列出。也许您可以在 Mockito 2.x 中模拟最终方法? (2认同)
  • 是的,我刚刚检查过,您现在可以在 Mockito 2.x 中模拟最终方法。我在答案中添加了如何操作:/sf/answers/3768623491/ (2认同)

iwe*_*ein 31

在Mockito中不支持嘲笑最终方法.

正如Jon Skeet评论的那样,你应该寻找一种方法来避免对最终方法的依赖.也就是说,通过字节码操作有一些方法(例如使用PowerMock)

Mockito和PowerMock之间比较将详细解释事情.

  • 链接似乎被打破了 (6认同)
  • 这个已经过期了。Mockito 2.x现在支持最终方法模拟(请参阅文档:https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-最终类模拟法) (5认同)
  • 这个答案已经过时了。Mockito 现在支持模拟最终方法。请参阅 https://www.baeldung.com/mockito-final。 (2认同)

Jus*_*owe 20

您可以将Powermock与Mockito一起使用,然后您不需要继承B.class.只需将其添加到测试类的顶部即可

@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)
Run Code Online (Sandbox Code Playgroud)

@PrepareForTest指示Powermock检测B.class以使最终和静态方法可模拟.这种方法的一个缺点是你必须使用PowerMockRunner,它不能使用其他测试运行器,例如Spring测试运行器.

  • 这对我不起作用.添加为建议但在不使用`@RunWith`和`@ PrepareForTest`时仍以相同的方式获得`NullPointerException`.似乎该课程由于某种原因没有被修改. (3认同)

Win*_*der 14

Mockito 2现在支持模拟最终方法,但这是一个"孵化"功能.它需要一些步骤来激活它,如下所述:https: //github.com/mockito/mockito/wiki/What's-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-最终classesmethods


Cyp*_*eld 6

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());
Run Code Online (Sandbox Code Playgroud)

在随后的里程碑中,团队将带来使用该功能的编程方式。我们将为所有无法模拟的场景确定并提供支持。

  • 我在 _SpringRunner_ 上尝试了这种方法,并为我想要的特定用例工作,但是在项目 _inlined_ 中制作所有模拟会破坏项目中的多个测试,所有测试都使用 _MockitoJUnitRunner_ 运行。如果有人想进一步调查,我可以提供更多细节。现在,我将等到该功能合并到 Mockito 代码库中,而不更改项目的所有模拟。 (2认同)