在软件开发中,单元测试是确保代码质量的重要环节。Mockito 是一个流行的 Java 模拟框架,它可以帮助我们轻松地创建和验证模拟对象的行为。本文将通过一个具体的实例,展示如何使用 Mockito 的 verify
方法来验证模拟对象的方法调用。
一、Mockito 的 verify
方法
Mockito 提供了强大的功能来验证模拟对象的方法是否被调用,以及调用时的参数是否符合预期。Mockito#verify(T mock)
方法用于确认特定的交互是否发生。换句话说,它可以帮助我们验证模拟对象的方法是否被正确调用。
二、实例应用
1. 示例应用代码
首先,我们定义一个简单的接口 MyService
和一个类 MyProcessor
,用于演示如何使用 Mockito 验证方法调用。
package com.logicbig.example;
public interface MyService {
public int doSomething(String processName);
}
package com.logicbig.example;
public class MyProcessor {
private String processName;
private MyService myService;
public MyProcessor(String processName, MyService myService) {
this.processName = processName;
this.myService = myService;
}
public void process() {
int returnInteger = processName != null ? myService.doSomething(processName) : -1;
System.out.println("My Integer is: " + returnInteger);
}
}
2. 测试代码
接下来,我们编写一个测试类 ProcessorTest
,使用 Mockito 来验证 MyService
的 doSomething
方法是否被正确调用。
package com.logicbig.example;
import org.junit.Test;
import org.mockito.Mockito;
public class ProcessorTest {
@Test
public void processTest() {
MyService myService = Mockito.mock(MyService.class);
String processName = "dummy-process-name";
Mockito.when(myService.doSomething(processName)).thenReturn(10);
MyProcessor myProcessor = new MyProcessor(processName, myService);
myProcessor.process();
Mockito.verify(myService).doSomething(processName);
}
}
3. 测试运行结果
运行上述测试代码,Maven 的输出如下:
[INFO] Scanning for projects...
[INFO]
[INFO] ---------< com.logicbig.example:mockito-verify-method-example >---------
[INFO] Building mockito-verify-method-example 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mockito-verify-method-example ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ mockito-verify-method-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mockito-verify-method-example ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ mockito-verify-method-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mockito-verify-method-example ---
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.logicbig.example.ProcessorTest
My Integer is: 10
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.732 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.671 s
[INFO] Finished at: 2020-07-23T00:08:57-05:00
[INFO] ------------------------------------------------------------------------
从输出结果可以看出,测试成功通过,MyService
的 doSomething
方法被正确调用。
4. 验证失败的情况
如果我们将测试代码中的 processName
设置为 null
,模拟对象的 doSomething
方法将不会被调用。此时,测试将失败。
package com.logicbig.example;
import org.junit.Test;
import org.mockito.Mockito;
public class ProcessorTest2 {
@Test
public void processTest() {
MyService myService = Mockito.mock(MyService.class);
String processName = null;
Mockito.when(myService.doSomething(processName)).thenReturn(10);
MyProcessor myProcessor = new MyProcessor(processName, myService);
myProcessor.process();
Mockito.verify(myService).doSomething(processName);
}
}
运行上述测试代码,Maven 的输出如下:
[INFO] Scanning for projects...
[INFO]
[INFO] ---------< com.logicbig.example:mockito-verify-method-example >---------
[INFO] Building mockito-verify-method-example 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mockito-verify-method-example ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ mockito-verify-method-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mockito-verify-method-example ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ mockito-verify-method-example ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mockito-verify-method-example ---
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.logicbig.example.ProcessorTest2
My Integer is: -1
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.055 sec <<< FAILURE!
processTest(com.logicbig.example.ProcessorTest2) Time elapsed: 0.916 sec <<< FAILURE!
Wanted but not invoked:
myService.doSomething(null);
-> at com.logicbig.example.ProcessorTest2.processTest(ProcessorTest2.java:16)
Actually, there were zero interactions with this mock.
从输出结果可以看出,测试失败,因为 MyService
的 doSomething
方法没有被调用。
三、总结
通过上述实例,我们可以看到 Mockito 的 verify
方法在单元测试中的重要作用。它可以帮助我们验证模拟对象的方法是否被正确调用,从而确保代码的行为符合预期。在实际开发中,合理使用 Mockito 的验证功能可以大大提高代码的可测试性和质量。
四、技术栈
- Mockito 核心版本:3.3.3
- JUnit 版本:4.13
- JDK:8
- Maven:3.5.4