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

Java 如何在没有powermock的情况下模拟静态方法,java,unit-testing,junit,mockito,powermock,Java,Unit Testing,Junit,Mockito,Powermock,在JUnit中进行测试时,有没有办法模拟静态util方法 我知道Powermock可以模拟静态调用,但我不想使用Powermock 有其他选择吗?(我想你可以使用Mockito)我脑子里没有什么特别的想法,但在这种情况下,我倾向于使用以下策略: 1)在测试的类中,将静态直接调用替换为对封装静态调用本身的包级方法的调用: public class ToBeTested{ public void myMethodToTest(){ ... String

在JUnit中进行测试时,有没有办法模拟静态util方法

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

有其他选择吗?

(我想你可以使用Mockito)我脑子里没有什么特别的想法,但在这种情况下,我倾向于使用以下策略:

1)在测试的类中,将静态直接调用替换为对封装静态调用本身的包级方法的调用:

public class ToBeTested{

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

    String makeStaticWrappedCall(){
        return Util.staticMethodCall();
    }
}
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();
    }
}
下面是我写的一篇关于间谍活动的文章,如果您需要更深入的了解,它包含了类似的案例:

当您的静态代码给您的单元测试带来麻烦时;因此,你觉得你必须“模仿它”,你有这些选择:

  • 你转向PowerMock(ito)。很好
  • 你转向JMockit。也很好用
  • 如果您正在测试自己编写的代码,您可能想退一步问问自己:“为什么我要编写现在很难进行单元测试的代码?”
换句话说:如果你想使用模拟框架,你必须使用上面列出的其中一个。一方面,这是绝对公平的。静态是Java语言的一部分;那么,为什么不使用一个允许您处理它的框架呢

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


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

我很幸运地做了一些类似于Maciej在上面的回答中所建议的事情。在Java8中,我喜欢用函数接口包装这些静态方法,使它们更易于注入或模拟。例如:

public class MyClass {
    private MyStaticWrapper staticWrapper;

    public MyClass(final MyStaticWrapper staticWrapper) {
        this.staticWrapper = staticWrapper;
    }

    public void main() {
        ...
        staticWrapper.doSomething();
        ...    
    }
}    

public interface MyStaticWrapper {
    default void doSomething() {
      Util.annoyingUntestableStaticFunction();
    }
}

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

给定一个类
Foo

class Foo{
  static String method() {
    return "foo";
  }
}
这就是测试:

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

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

即使使用mockito,也不能模拟静态方法。您不想使用powermock有什么原因吗?您必须模拟它吗?这是你的代码,你可以重写它,这样就不会有静态?我注意到你的问题仍然是“开放的”——因为你没有接受答案。请看一看,然后决定是否要回答。或者让我知道是否有什么我可以做的,以加强我的投入,使其值得接受。接受帮助未来的读者确定问题是否得到解决,并对花时间回答你的人表示感谢。谢谢@UweAllner,不使用PosiMoCK的一个原因是像JACCOO这样的代码覆盖工具可能不考虑通过代码覆盖报告中的PosiMoCK来覆盖代码。当问题明确地询问静态方法时,如何调用构造函数?当所有方法都是静态的时候调用构造函数不是没有用吗?此外,在这种情况下,监视也将是无用的。如果类不是final,他可以将子类
添加到tobetest
中,添加包装器方法并测试子类。我得到一个错误
想要但未调用:
,实际上,当我尝试验证是否调用了该方法时,没有与该模拟进行任何交互。
我使用org.mockito:mockito inline:3.4.0和更新版本,并复制了与上述相同的代码。但我仍然得到“MockedStatic”和“mockStatic”的编译错误。它不显示任何导入语句。我尝试使用import org.mockito.*;但在使用编辑过的答案后,它也不起作用,我得到了编译错误,因为“MockedStatic无法解析为类型”。我们需要特殊的进口声明吗。我的pom.xml依赖项添加为org.mockito mockito inline 3.5.9@user2000189您使用的是
SpringBoot
?最新版本的
spring boot
(2.3.3.版本)不支持Mockito 3.4.0。如果您想使用它,您需要将
org.mockito:mockito core
强制到3.4.0版。我使用的是spring boot(2.3.1-RELEASE)和mockito core作为3.3.3。@user2000189将
mockito core
强制到3.4.0版可以让您运行这个示例,但是要注意其他潜在的问题,因为Spring还没有正式支持它。您好,您有关于这个的单元测试的例子吗?