Mockito 3 未被调用,但期望被调用

huangapple go评论85阅读模式
英文:

Mockito 3 Wanted but not invoked

问题

我正在尝试学习Mockito 3,我已经查看了几乎所有谷歌搜索结果,但找不到可行的解决方案。
我在测试用例中调用processStudent方法,该方法根据输入基于内部调用另一个方法saveStudentsaveNullStudent

我需要同时测试这两种情况,所以我的测试用例是:

@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();
	}

}

huangapple
  • 本文由 发表于 2020年7月23日 23:26:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63057753.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定