在Mockito中是否可能模拟既是静态的又是void的方法?

huangapple go评论89阅读模式
英文:

Is it possible to mock a method that is both static and void using Mockito?

问题

我试图避免在这里使用PowerMockito。我们有包含静态和void方法的遗留代码,还有需要模拟它们的测试。是否有方法可以做到这一点,或者重构遗留代码是唯一的方法?

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

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

异常信息:

org.mockito.exceptions.misusing.UnfinishedStubbingException:
在这里检测到未完成的存根设置
-> 在 com.mytests.Test.setMock(Test.java:35)

例如可能缺少 thenReturn()
正确存根设置的示例
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
提示
 1. 缺少 thenReturn()
 2. 你正在尝试存根一个final方法这是不受支持的
 3. 在 before 'thenReturn' 指令完成之前你正在存根另一个模拟的行为

注意:请注意,我想要模拟的方法既是静态的又是void的。

英文:

I'm trying to avoid using PowerMockito here. We have legacy code which contains methods that are both static and void and there are tests which need to mock them. Is there a way to do it or is refactoring legacy code the only way here?

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

If I use the general MockStatic syntax, it asks me to return something:

MockedStatic &lt;MySample&gt; sampleMock = Mockito.mockStatic( MySample.class );
sampleMock.when(() -&gt; MySample.sampleMethod(Mockito.any(String.class)));

Exception:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-&gt; 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 &#39;thenReturn&#39; instruction is completed

Edit: Please note that I'm looking to mock a method that is BOTH static and void.

答案1

得分: 4

当模拟的方法被调用时,您希望发生什么?

默认行为是什么都不会发生。通过调用 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 -> {
        // 插入要执行的其他代码
        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在 这个答案 中所指出的,即使您覆盖了默认行为,真实方法仍然会被调用!这可能会在将来修复;请参考Marc的答案以获取一些良好的参考资料。

英文:

What do you want to happen when the mocked method gets called?

The default behavior is that nothing happens. By calling sampleMock.when(), you indicated that you wanted to change from the default behavior to something else. Mockito is complaining because you didn't then follow that up with a call to then___() to specify what should happen instead.

There are a few different things I can think of that you might want to have happen:

1. Do nothing

As previously stated, this is the default behavior, so if this is all you want, you can just remove the second line and it should work. But, if you really need to have a when call (e.g. for argument capture), you can instead finish off the line with an empty thenAnswer:

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

2. Call the real method

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

3. Do something else

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

4. Throw an exception

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

Update

As previously mentioned, the default behavior is to do nothing, but I learned it's also possible to specify an alternate default behavior by providing an Answer when creating the mock. For example, to have the default behavior call the real method instead:

MockedStatic &lt;MySample&gt; sampleMock = Mockito.mockStatic( MySample.class, Mockito.CALLS_REAL_METHODS );

But beware - as noted by Marc in this answer, the real method will still be called even if you override the default behavior! This may be fixed in the future; see Marc's answer for some good references

答案2

得分: 0

@RunWith(PowerMockRunner.class) 添加到你的类头部将阻止抛出前面提到的异常类型!

英文:

Adding @RunWith(PowerMockRunner.class) to your class header will prevent the throw of the aforementioned exception type!

huangapple
  • 本文由 发表于 2020年9月11日 00:58:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/63834381.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定