Mockito 3 想要但没有调用
Mockito 3 Wanted but not invoked
我正在尝试学习 Mockito 3,我几乎查看了 google 搜索中的所有结果,但找不到有效的解决方案。
我在一个测试用例中调用 processStudent
,该测试用例根据输入在内部调用另一个方法 saveStudent
或 saveNullStudent
。
public String processStudent(String student) {
System.out.println("StudentService.processStudent: it will process Student = " + student);
String StudentRes;
if (Objects.isNull(student)) {
StudentRes = saveNullStudent(student);
return StudentRes;
} else {
StudentRes = saveStudent(student);
return StudentRes;
}
}
public String saveNullStudent(String student) {
System.out.println("StudentService.saveNullStudent: it will process then save Student = " + student);
return student;
}
public String saveStudent(String student) {
System.out.println("StudentService.saveStudent: it will process then save Student = " + student);
return student;
}
我需要测试这两个案例,所以我的测试案例是
@Test
void saveStudentWithMockTest() {
StudentService StudentService = mock(StudentService.class);
StudentService.processStudent("studentA");
verify(StudentService, times(1)).saveStudent("studentA");
}
@Test
void saveStudentWithNullMockTest() {
StudentService StudentService = mock(StudentService.class);
StudentService.processStudent(null);
verify(StudentService, times(1)).saveNullStudent(null);
}
但我得到了
Wanted but not invoked:
studentService.saveNullStudent(null);
-> at StudentServiceTest.saveStudentWithNullMockTest(StudentServiceTest.java:21)
However, there was exactly 1 interaction with this mock:
studentService.processStudent(null);
-> at StudentServiceTest.saveStudentWithNullMockTest(StudentServiceTest.java:20)
Gradle 文件
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
我不明白,这不是mockito的用途吗?
这个测试用例的重点不是单元测试,而是测试 processStudent
方法的行为,如果值为 null,则根据输入数据调用 saveNullStudent
方法,或者else saveStudent
方法被调用。
我做错了什么?
您在模拟对象上调用 processStudent
,这意味着未使用原始代码。因此 save
方法没有被调用。
您需要更改模拟,因此使用 thenCallRealMethod()
调用真正的方法。
在您的第一个测试中,您必须添加如下一行:
when(StudentService.processStudent("studentA")).thenCallRealMethod()
在第二个测试中它是相似的,但是有另一个参数。
也许语法不是 100% 正确,因为我在没有任何 IDE 支持的情况下写这篇文章,但我想你明白了。
你应该先了解什么是模拟对象。那么解决方案将更有意义。
您应该只模拟要测试的 class 的依赖项。我的意思是,如果 StudentService
class 有任何全局变量,如其他服务或存储库 classes 那些是你应该模拟的 classes。 StudentService
class 本身应该是真实的。在您的案例中更好的测试是检查两个测试用例的 processStudent
方法的输出。例如:
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class StudentServiceTest {
private final StudentService studentService = new StudentService();
@Test
public void saveStudentWithMockTest() {
String result = studentService.processStudent("studentA");
assertThat(result).isEqualToIgnoringCase("studentA");
}
@Test
public void saveStudentWithNullMockTest() {
String result = studentService.processStudent(null);
assertThat(result).isNull();
}
}
我正在尝试学习 Mockito 3,我几乎查看了 google 搜索中的所有结果,但找不到有效的解决方案。
我在一个测试用例中调用 processStudent
,该测试用例根据输入在内部调用另一个方法 saveStudent
或 saveNullStudent
。
public String processStudent(String student) {
System.out.println("StudentService.processStudent: it will process Student = " + student);
String StudentRes;
if (Objects.isNull(student)) {
StudentRes = saveNullStudent(student);
return StudentRes;
} else {
StudentRes = saveStudent(student);
return StudentRes;
}
}
public String saveNullStudent(String student) {
System.out.println("StudentService.saveNullStudent: it will process then save Student = " + student);
return student;
}
public String saveStudent(String student) {
System.out.println("StudentService.saveStudent: it will process then save Student = " + student);
return student;
}
我需要测试这两个案例,所以我的测试案例是
@Test
void saveStudentWithMockTest() {
StudentService StudentService = mock(StudentService.class);
StudentService.processStudent("studentA");
verify(StudentService, times(1)).saveStudent("studentA");
}
@Test
void saveStudentWithNullMockTest() {
StudentService StudentService = mock(StudentService.class);
StudentService.processStudent(null);
verify(StudentService, times(1)).saveNullStudent(null);
}
但我得到了
Wanted but not invoked:
studentService.saveNullStudent(null);
-> at StudentServiceTest.saveStudentWithNullMockTest(StudentServiceTest.java:21)
However, there was exactly 1 interaction with this mock:
studentService.processStudent(null);
-> at StudentServiceTest.saveStudentWithNullMockTest(StudentServiceTest.java:20)
Gradle 文件
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
我不明白,这不是mockito的用途吗?
这个测试用例的重点不是单元测试,而是测试 processStudent
方法的行为,如果值为 null,则根据输入数据调用 saveNullStudent
方法,或者else saveStudent
方法被调用。
我做错了什么?
您在模拟对象上调用 processStudent
,这意味着未使用原始代码。因此 save
方法没有被调用。
您需要更改模拟,因此使用 thenCallRealMethod()
调用真正的方法。
在您的第一个测试中,您必须添加如下一行:
when(StudentService.processStudent("studentA")).thenCallRealMethod()
在第二个测试中它是相似的,但是有另一个参数。 也许语法不是 100% 正确,因为我在没有任何 IDE 支持的情况下写这篇文章,但我想你明白了。
你应该先了解什么是模拟对象。那么解决方案将更有意义。
您应该只模拟要测试的 class 的依赖项。我的意思是,如果 StudentService
class 有任何全局变量,如其他服务或存储库 classes 那些是你应该模拟的 classes。 StudentService
class 本身应该是真实的。在您的案例中更好的测试是检查两个测试用例的 processStudent
方法的输出。例如:
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class StudentServiceTest {
private final StudentService studentService = new StudentService();
@Test
public void saveStudentWithMockTest() {
String result = studentService.processStudent("studentA");
assertThat(result).isEqualToIgnoringCase("studentA");
}
@Test
public void saveStudentWithNullMockTest() {
String result = studentService.processStudent(null);
assertThat(result).isNull();
}
}