英文:
Mockito 3 Wanted but not invoked
问题
我正在尝试学习Mockito 3,我已经查看了几乎所有谷歌搜索结果,但找不到可行的解决方案。
我在测试用例中调用processStudent
方法,该方法根据输入基于内部调用另一个方法saveStudent
或saveNullStudent
。
我需要同时测试这两种情况,所以我的测试用例是:
@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
方法,否则调用saveStudent
方法。
我做错了什么?
英文:
I am trying to learn Mockito 3, I have looked almost all the results in google search, but couldn't find the working solution.
I am calling processStudent
in a test case which on the basis of input internally calls another method saveStudent
or 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;
}
I need to test both the cases so my Test case is
@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);
}
but I am getting
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 file
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
I don't understand, isn't this is what mockito is for?
the whole point of this test case is not for a unit test but to test the behavior of processStudent
method that as per input data if the value is null then saveNullStudent
method is called or else saveStudent
method is called.
what I am doing wrong?
答案1
得分: 0
你在一个模拟对象上调用了 processStudent
方法,这意味着原始代码未被使用。因此 save
方法不会被调用。
你需要修改模拟对象,以便通过使用 thenCallRealMethod()
调用真实方法。
在你的第一个测试中,你需要添加一行代码,类似于:
when(StudentService.processStudent("studentA")).thenCallRealMethod();
在第二个测试中,情况类似,只是使用了另一个参数。
也许语法不是100%正确的,因为我是在没有任何IDE支持的情况下编写的,但我想你可以理解我的意思。
你应该先了解什么是模拟对象。然后解决方案会更加明确。
英文:
You call the processStudent
on a mock object, this means, that the original code is not used. Therefore the save
method is not invoked.
You need to change the mock, so the real method is invoked by using thenCallRealMethod()
.
In your first test you have to add a line like:
when(StudentService.processStudent("studentA")).thenCallRealMethod()
In the second test it is similar, but with another parameter.
Maybe the syntax is not 100% correct, because I am writing this without any IDE support, but I think you get the idea.
You should learn what a mock object is first. Then the solution will make more sense.
答案2
得分: 0
你应该只模拟你想要测试的类的依赖关系。我的意思是,如果StudentService
类有任何全局变量,比如其他服务类或存储库类,那么这些类就是你应该模拟的类。StudentService
类本身应该是真实的。在你的情况下,更好的测试方法是检查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();
}
}
英文:
You should only mock the dependencies of the class that you want to test. By which I mean, if the StudentService
class has any global variables like other service or repository classes those are the classes that you should mock. The StudentService
class itself should be real. A better test in your case would be to check the output of the processStudent
method for both test cases. Eg:
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();
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论