使用 doReturn 而不是 whenThen 时,Mockito 未检测到对服务存储库的调用
Mockito not detecting call on repository of service when using doReturn instead of whenThen
我对 Mocking 还比较陌生,但是我读了很多书,也上了 udemy 的课程(不像我是专家,离它很远,只是说我一直在研究这个) , 但我还是想不通。
我读了这个postMockito - difference between doReturn() and when(),这让我明白了一些事情。
现在让我解释一下我的问题。
我有一个服务实现 class,可以根据需要调用存储库 class 到 get/do。这项服务 class 是我正在为其编写 mockito 测试的服务。
这个问题可以通过两种不同的方式解决。
第一种方式:(when thenReturn)
我的测试 class 看起来像这样(伪代码):
serviceImplCastTest {
@Spy
@InjectMocks
ServiceImplClass serviceImplClass;
@Mock
RepositoryClass repositoryClass;
@Test
void whenMethodInService_thenReturnNonEmptyMap() {
List<Class> classList = new ArrayList<~>();
Class class = new Class("Whatever");
classList.Add(class)
Map<String, Class> classMap = classList.stream.collect(Collectors.toMap(Class::getMethod, Function.identity()));
when(serviceImplClass.methodInService()).thenReturn(classMap);
Map<String, Class> actualMap = serviceImplClass.methodInService();
assertFalse(actualMap.isEmpty());
verify(repositoryClass, times(1)).methodInRepository();
}
因此,这不起作用,因为服务中的方法(return是一个地图)调用存储库中的一个方法,该方法return是一个 Class 的列表,然后我在服务中的方法将该列表转换为地图,出于某种原因,Mockito 需要 Class 的列表,而不是地图。我收到 Mockito 错误类型的 return 错误。
(如果服务方法 return 与存储库 return 的列表类型相同,则此代码可以完美运行。)
第二种方式:(doReturn when)
serviceImplCastTest {
@Spy
@InjectMocks
ServiceImplClass serviceImplClass;
@Mock
RepositoryClass repositoryClass;
@Test
void whenMethodInService_thenReturnNonEmptyMap() {
List<Class> classList = new ArrayList<~>();
Class class = new Class("Whatever");
classList.Add(class)
Map<String, Class> classMap = classList.stream.collect(Collectors.toMap(Class::getMethod, Function.identity()));
doReturn(classMap).when(serviceImplClass).methodInService();
Map<String, Class> actualMap = serviceImplClass.methodInService();
assertFalse(actualMap.isEmpty());
verify(repositoryClass, times(1)).methodInRepository();
}
现在,当使用 doReturn 时,一切正常, 除了 验证,repositoryClass.methodInRepository() 没有被调用,或者至少没有被正确侦测或者什么的,Mockito 抛出错误“想要但未调用”。
所以我不确定如何在 Mockito 端解决这个问题,因为一个简单的方法是更改逻辑,服务 return 列表而不是映射,然后更改我的应用程序以接收列表并映射它那边,但是这意味着影响逻辑,我被禁止这样做。
此外,我真的很想能够模拟这个,因为我还有其他一些等效的情况,其中我的服务 class 处理列表然后将其转换成其他东西,并且模拟仍然期望要 returned 的列表。
我怎样才能嘲笑这个?正确的做法是什么?
您在两个代码片段中都犯了同样的错误,因为您在尝试测试的 class 中存根了一个方法,而不是在模拟的 class.
这意味着您实际上只是在测试存根,而不是在测试 class 本身。
你想做的是
- 摆脱 Spy 注释 - 你不需要间谍。
- 存根存储库 class 的方法,而不是服务 class。
这样,您将测试服务 class 是否正确调用存储库 class,并正确处理来自存储库 class 的响应。但是你也会绕过存储库的实现class,这是使用模拟的全部意义。
我对 Mocking 还比较陌生,但是我读了很多书,也上了 udemy 的课程(不像我是专家,离它很远,只是说我一直在研究这个) , 但我还是想不通。
我读了这个postMockito - difference between doReturn() and when(),这让我明白了一些事情。
现在让我解释一下我的问题。
我有一个服务实现 class,可以根据需要调用存储库 class 到 get/do。这项服务 class 是我正在为其编写 mockito 测试的服务。
这个问题可以通过两种不同的方式解决。
第一种方式:(when thenReturn)
我的测试 class 看起来像这样(伪代码):
serviceImplCastTest {
@Spy
@InjectMocks
ServiceImplClass serviceImplClass;
@Mock
RepositoryClass repositoryClass;
@Test
void whenMethodInService_thenReturnNonEmptyMap() {
List<Class> classList = new ArrayList<~>();
Class class = new Class("Whatever");
classList.Add(class)
Map<String, Class> classMap = classList.stream.collect(Collectors.toMap(Class::getMethod, Function.identity()));
when(serviceImplClass.methodInService()).thenReturn(classMap);
Map<String, Class> actualMap = serviceImplClass.methodInService();
assertFalse(actualMap.isEmpty());
verify(repositoryClass, times(1)).methodInRepository();
}
因此,这不起作用,因为服务中的方法(return是一个地图)调用存储库中的一个方法,该方法return是一个 Class 的列表,然后我在服务中的方法将该列表转换为地图,出于某种原因,Mockito 需要 Class 的列表,而不是地图。我收到 Mockito 错误类型的 return 错误。
(如果服务方法 return 与存储库 return 的列表类型相同,则此代码可以完美运行。)
第二种方式:(doReturn when)
serviceImplCastTest {
@Spy
@InjectMocks
ServiceImplClass serviceImplClass;
@Mock
RepositoryClass repositoryClass;
@Test
void whenMethodInService_thenReturnNonEmptyMap() {
List<Class> classList = new ArrayList<~>();
Class class = new Class("Whatever");
classList.Add(class)
Map<String, Class> classMap = classList.stream.collect(Collectors.toMap(Class::getMethod, Function.identity()));
doReturn(classMap).when(serviceImplClass).methodInService();
Map<String, Class> actualMap = serviceImplClass.methodInService();
assertFalse(actualMap.isEmpty());
verify(repositoryClass, times(1)).methodInRepository();
}
现在,当使用 doReturn 时,一切正常, 除了 验证,repositoryClass.methodInRepository() 没有被调用,或者至少没有被正确侦测或者什么的,Mockito 抛出错误“想要但未调用”。
所以我不确定如何在 Mockito 端解决这个问题,因为一个简单的方法是更改逻辑,服务 return 列表而不是映射,然后更改我的应用程序以接收列表并映射它那边,但是这意味着影响逻辑,我被禁止这样做。
此外,我真的很想能够模拟这个,因为我还有其他一些等效的情况,其中我的服务 class 处理列表然后将其转换成其他东西,并且模拟仍然期望要 returned 的列表。
我怎样才能嘲笑这个?正确的做法是什么?
您在两个代码片段中都犯了同样的错误,因为您在尝试测试的 class 中存根了一个方法,而不是在模拟的 class.
这意味着您实际上只是在测试存根,而不是在测试 class 本身。
你想做的是
- 摆脱 Spy 注释 - 你不需要间谍。
- 存根存储库 class 的方法,而不是服务 class。
这样,您将测试服务 class 是否正确调用存储库 class,并正确处理来自存储库 class 的响应。但是你也会绕过存储库的实现class,这是使用模拟的全部意义。