【问题标题】:Is it possible to mock a method that is both static and void using Mockito?是否可以使用 Mockito 模拟一个既是静态又是 void 的方法?
【发布时间】:2021-02-19 16:28:32
【问题描述】:

我试图避免在这里使用 PowerMockito。我们有遗留代码,其中包含静态和无效的方法,并且有需要模拟它们的测试。有没有办法做到这一点,或者重构遗留代码是这里的唯一方法?

class MySample {
       public static void sampleMethod(String argument){
                //do something
       }
}

如果我使用通用的 MockStatic 语法,它会要求我返回一些内容:

MockedStatic <MySample> sampleMock = Mockito.mockStatic( MySample.class );
sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)));

例外:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at com.mytests.Test.setMock(Test.java:35)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, which is not supported
 3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed

编辑:请注意,我希望模拟一个既是静态又是 void 的方法。

【问题讨论】:

  • 这能回答你的问题吗? How to mock static method without powermock
  • 感谢您的回答,但引用的示例不适用于 void 方法。
  • @Slaw 该问题中接受的答案希望我们有一个实例,但这里的测试方法是静态的。有没有静态和无效方法的示例?

标签: java mockito


【解决方案1】:

当被模拟的方法被调用时你想发生什么?

默认行为是什么都没有发生。通过调用sampleMock.when(),您表明您想从默认行为更改为其他行为。 Mockito 之所以抱怨,是因为您没有随后致电then___() 来指定应该发生的事情。

我能想到你可能希望发生的一些不同的事情:

1。什么都不做

如前所述,这是默认行为,所以如果这是您想要的,您可以删除第二行,它应该可以工作。但是,如果你真的需要一个 when 调用(例如用于参数捕获),你可以用一个空的 thenAnswer 结束行:

sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)))
    .thenAnswer(invocation -> null);

2。调用真正的方法

sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)))
    .thenCallRealMethod();

3。做点别的事情

sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)))
    .thenAnswer(invocation -> {
        // insert code to do something else here
        return null;
    });

4。抛出异常

sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)))
    .thenThrow(RuntimeException.class);

更新

如前所述,默认行为是什么都不做,但我了解到,还可以通过在创建模拟时提供Answer 来指定替代默认行为。例如,让默认行为改为调用真实方法:

MockedStatic <MySample> sampleMock = Mockito.mockStatic( MySample.class, Mockito.CALLS_REAL_METHODS );

但请注意 - 正如 Marc 在 this answer 中所指出的,即使您覆盖了默认行为,仍会调用真正的方法!这可能会在未来得到解决;请参阅 Marc 的回答以获取一些好的参考资料

【讨论】:

  • 感谢您回答@Kevin K,您能否看看这个问题:stackoverflow.com/q/63840898/1668384
  • @Kumar 我了解到可以更改默认的模拟行为并在此处更新答案以告知这一点。我认为这也应该回答你的另一个问题;如果您可以确定调用真实方法的默认行为,那么您可以为您要模拟的特定方法添加when/then 规则。
  • @KevinK 您的更新是正确的,但默认行为 .callRealMethod() 将始终触发静态方法,即使被存根。关于我的回答的更多细节stackoverflow.com/a/63841319/8484783
  • 谢谢@Marc,很高兴知道。另外我不知道Mockito.CALLS_REAL_METHODS,这很有用,将为此更新我的示例
【解决方案2】:

@RunWith(PowerMockRunner.class) 添加到您的类头将防止上述异常类型的抛出!

【讨论】:

    猜你喜欢
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 2014-02-02
    相关资源
    最近更新 更多