Mockito 存根静态方法,它调用对象上的方法



有一个Service类和一个Util类,有两个静态方法,如图所示。

public class Service {
public String doSomething() {
return "something";
}
}
public final class Util {
public static String utilFuncCallingService(Service service) {
//some code
System.out.println("Util class calling doSomething on service");
return service.doSomething();
}
public static String utilFuncReturningString() {
return "string";
}
}

主类 (SUT) 是,

public class MyClass {
public final Service service;
public MyClass(Service service) {
this.service = service;
}
public void method() {
System.out.println("Response: " + Util.utilFuncCallingService(service));
}
}

它调用传递Service实例的Util.utilFuncCallingService方法。

JUnit 测试是:

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Mock
private Service service;
@Before
public void setup() {
when(Util.utilFuncCallingService(service))
.thenReturn("mock-response");
}
@Test
public void test() {
MyClass myClass = new MyClass(service);
myClass.method();
}
}

运行这个,它打印,

Util class calling doSomething on service
Util class calling doSomething on service
Response: mock-response

第一行在测试setup期间打印,第二行在实际测试期间打印。

  1. 存根调用when(Util.utilFuncCallingService(service)).thenReturn(..)如何等同于在这里写when(service.doSomething()).thenReturn("mock-response")

Mockito不允许我们存根Util.utilFuncReturningString()因为它是一种静态方法。存根调用Util.utilFuncCallingService()在这里是如何工作的?

我与 JUnit 合作过很多次,但我觉得我在这里缺少一些非常基本的东西。

这个问题有几个部分。

首先,Mockito确实支持模拟静态方法。

@ExtendWith(MockitoExtension.class)
public class MyClassTest {
@Mock
private Service service;
@Test
public void test() {
try(MockedStatic<Util> dummyStatic = Mockito.mockStatic(Util.class)) {
dummyStatic.when(() -> Util.utilFuncCallingService(service)).thenReturn("mock-response");
MyClass myClass = new MyClass(service);
myClass.method();
}
}
}
// Prints: Response: mock-response

第二,你的测试出了什么问题,为什么莫基托没有抱怨?

你需要知道 Mockito 存根是一个基于堆栈的机器 - 如果你在调用Mockito.when时在内部的模拟上调用一个方法,这个调用是在堆栈上注册的,因此 mockito 知道要存根哪个方法。

在您的测试中,您调用了被执行的Util.utilFuncCallingService(service),而又调用了service.doSomething()- 这是对模拟的方法调用,因此它落在堆栈上。模拟上没有其他方法调用,因此 suubbed 方法service.doSomething()

观察:

@ExtendWith(MockitoExtension.class)
public class MyClassTest {
@Mock
private Service service;
@Test
public void test() {
when(Util.utilFuncCallingService(service)).thenReturn("mock-response");
System.out.println(service.doSomething());
}
}
// Prints:
// Util class calling doSomething on service
// mock-response

你可以看看:

  • 解释基于代理的模拟框架如何工作
  • 当()调用时,mockito 如何工作?
  • 莫基托匹配器如何工作?

最新更新