这里有一个Service类和一个Util类,其中有两个static方法,如图所示.

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存根是一台基于堆栈的机器--如果在调用Mockito.when时在mock内部调用一个方法,则此调用注册在堆栈上,因此moockito知道要存根的方法.

在您的测试中,您调用了Util.utilFuncCallingService(service),然后被执行,而后者又调用了service.doSomething()--这是对模拟的方法调用,所以它位于堆栈上.在mock上没有其他方法调用,所以推荐的方法是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

您可以查看以下内容:

Java相关问答推荐

如何粘合(合并)文件Lucene?

为什么一个java函数会返回一个作为参数传递给它的对象?

是否保证在事务性块的末尾标记违反约束?

如何获得执行人?

AssertJ Java:多条件断言

为什么JAVA&S清洁器使用链表而不是并发HashSet?

蒙蒂霍尔比赛结果不正确

由于我在Main方法中关闭了 scanner ,但在该方法中创建了一个新的 scanner ,因此出现了错误

解释左移在Java中的工作原理

基于接口的投影、原生查询和枚举

由于在生成器模式中使用泛型,lambda表达式中的返回类型错误

允许同时执行两个方法,但不能同时执行这两个方法

X=x*0.90;产生有损转换误差.X*=0.90;不是.为什么?

除0错误/抱歉我的句子是PT

使用for循环时出现堆栈溢出错误,但如果使用if块执行相同的操作,则不会产生错误

验证没有';t work on Hibernate Entity';s字段

[jdk21][Foreign Function&;Memory API]MemoryLayout::varHandle通过可变数组进行 struct 化的问题

Java 8 中 ByteBuffer 和 BitSet 的奇怪行为

如何在 Android Studio 中删除 ImageView 和屏幕/父级边缘之间的额外空间?

如何在 Visual Studio 代码中快速生成构造函数和 getter、setter?