如何使用Mockito模拟类中的单个静态方法?

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

How to mock just one static method in a class using Mockito?

问题

以下是翻译好的内容:

以下一行似乎是在模拟类中的所有静态方法:

MockedStatic<Sample> sampleMock = Mockito.mockStatic(Sample.class);
sampleMock.when(() -> Sample.sampleStaticMethod(Mockito.any(String.class))).thenReturn("response");

是否有可能仅模拟类中的一个静态方法?

英文:

The following line seems to mock all static methods in the class:

MockedStatic &lt;Sample&gt; sampleMock = Mockito.mockStatic( Sample.class );
sampleMock.when( () -&gt; Sample.sampleStaticMethod( Mockito.any( String.class ) ) ).thenReturn( &quot;response&quot; );

Is it possible to mock just one static method in a class?

答案1

得分: 57

默认情况下,所有方法都被模拟。然而,使用Mockito.CALLS_REAL_METHODS,您可以配置模拟以实际触发真实方法,仅排除一个方法。

例如,给定类Sample

class Sample{
    static String method1(String s) {
        return s;
    }
    static String method2(String s) {
        return s;
    }
}

如果我们只想模拟method1

@Test
public void singleStaticMethodTest(){
    try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
        mocked.when(() -> Sample.method1(anyString())).thenReturn("bar");
        assertEquals("bar", Sample.method1("foo")); // 被模拟
        assertEquals("foo", Sample.method2("foo")); // 未被模拟
    }
}

请注意,真正的Sample.method1()仍然会被调用。根据Mockito.CALLS_REAL_METHODS文档:

当处理旧代码时,此实现可能会很有帮助。当使用此实现时,未存根的方法将委托给真正的实现。这是一种创建默认调用真实方法的部分模拟对象的方式。
...

注意1:使用when(mock.getSomething()).thenReturn(fakeValue)语法存根部分模拟将调用真正的方法。对于部分模拟,建议使用doReturn语法。

因此,如果您不希望完全触发存根的静态方法,解决方案是使用doReturn语法(正如文档建议的那样),但是对于静态方法仍然不受支持:

@Test
public void singleStaticMethodTest() {
    try (MockedStatic<Sample> mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
        doReturn("bar").when(mocked).method1(anyString()); // 编译错误!
        //...
    }
}

关于这个问题,请查看此问题

英文:

By default all methods are mocked. However, using Mockito.CALLS_REAL_METHODS you can configure the mock to actually trigger the real methods excluding only one.

For example given the class Sample:

class Sample{
	static String method1(String s) {
		return s;
	}
	static String method2(String s) {
		return s;
	}
}

If we want to mock only method1:

@Test
public void singleStaticMethodTest(){
	try (MockedStatic&lt;Sample&gt; mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
		mocked.when(() -&gt; Sample.method1(anyString())).thenReturn(&quot;bar&quot;);
		assertEquals(&quot;bar&quot;, Sample.method1(&quot;foo&quot;)); // mocked
		assertEquals(&quot;foo&quot;, Sample.method2(&quot;foo&quot;)); // not mocked
	}
}

Be aware that the real Sample.method1() will still be called. From Mockito.CALLS_REAL_METHODS docs:

> This implementation can be helpful when working with legacy code. When
> this implementation is used, unstubbed methods will delegate to the
> real implementation. This is a way to create a partial mock object
> that calls real methods by default.
> ...

> Note 1: Stubbing partial mocks using
> when(mock.getSomething()).thenReturn(fakeValue) syntax will call the
> real method. For partial mock it's recommended to use doReturn
> syntax.

So if you don't want to trigger the stubbed static method at all, the solution would be to use the syntax doReturn (as the doc suggests) but for static methods is still not supported:

@Test
public void singleStaticMethodTest() {
	try (MockedStatic&lt;Sample&gt; mocked = Mockito.mockStatic(Sample.class,Mockito.CALLS_REAL_METHODS)) {
		doReturn(&quot;bar&quot;).when(mocked).method1(anyString()); // Compilation error!
		//...
	}
}

About this check this issue.

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

发表评论

匿名网友

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

确定