如何在没有powermock的情况下模拟静态方法

gat*_*ahu 19 java junit unit-testing mockito powermock

有没有什么办法可以在junit中测试时模拟静态util方法?

我知道Powermock可以模拟静态调用; 但我不想使用Powermock.

还有其他选择吗?

Mac*_*ski 14

(我假设你可以使用Mockito)我没有任何专用的东西,但我倾向于使用以下策略:

1)在被测试的类中,使用包装静态调用本身的包级别方法调用替换静态直接调用:

public class ToBeTested{

    public void myMethodToTest(){
         ...
         String s = makeStaticWrappedCall();
         ...
    }

    String makeStaticWrappedCall(){
        return Util.staticMethodCall();
    }
}
Run Code Online (Sandbox Code Playgroud)

2)在测试时监视被测试的类并模拟包装的包级别方法:

public class ToBeTestedTest{

    @Spy
    ToBeTested tbTestedSpy = new ToBeTested();

    @Before
    public void init(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void myMethodToTestTest() throws Exception{
       // Arrange
       doReturn("Expected String").when(tbTestedSpy).makeStaticWrappedCall();

       // Act
       tbTestedSpy.myMethodToTest();
    }
}
Run Code Online (Sandbox Code Playgroud)


Gho*_*ica 10

当您的静态代码在单元测试中给您带来麻烦时;所以你觉得你必须“嘲笑它”,你有这些选择:

  • 你转向 PowerMock(ito)。工作正常。
  • 你转向 JMockit。工作正常,也是。
  • 如果您正在测试自己编写的代码,您可能想退后一步问问自己:“为什么我编写的代码现在很难进行单元测试?”

换句话说:如果您想使用模拟框架,则必须使用上面列出的框架之一。一方面,这绝对是公平的。静态是 Java 语言的一部分;那么为什么不使用允许您处理它的框架呢?

但是当然:那时您的生产代码中仍然有静态调用。导致紧耦合,防止多态

所以:如果你能摆脱静态调用(即使只是使用另一个答案中建议的解决方法) - 那就更好了。如果不是:Mockito 无能为力;你需要字节码操作的魔力。JVM 代理。


Mar*_*arc 5

您可以使用Mockito(自3.4.0版起)来模拟静态方法。

给定一个类Foo

class Foo{
  static String method() {
    return "foo";
  }
}
Run Code Online (Sandbox Code Playgroud)

这是测试:

@Test
void testMethod() {
    assertEquals("foo", Foo.method());
    try (MockedStatic mocked = Mockito.mockStatic(Foo.class)) {
        mocked.when(Foo::method).thenReturn("bar");
        assertEquals("bar", Foo.method());
        mocked.verify(Foo::method);
    }
    assertEquals("foo", Foo.method());
}
Run Code Online (Sandbox Code Playgroud)

这需要依赖项org.mockito:mockito-inline:3.4.0或更新的版本。