更多Mockito RETURNS_DEEP_STUBS的问题

时间:2017-10-23 22:31:51

标签: java spring unit-testing testing mockito

我最近阅读并使用了下面链接的GitHub Repo中的一些示例,这些示例用于扩展基本的Spring Boot错误对象。我正在尝试为ApiError.java类编写一些测试,特别是#addValidationErrors

https://github.com/brunocleite/spring-boot-exception-handling/blob/master/src/main/java/com/example/springbootexceptionhandling/ApiError.java

基本问题是我没有找到方法来链接方法以返回值。我此时的测试看起来像这样......

@Test
public void addValidationErrors() {
    ApiError apiError = new ApiError(HttpStatus.OK);
    ConstraintViolation mockViolation = Mockito.mock(ConstraintViolation.class, Mockito.RETURNS_DEEP_STUBS);
    Mockito.when(mockViolation.getRootBeanClass().getSimpleName()).thenReturn("MyBeanName");
...

此时,测试在行上调用NullPointerException,调用Mockito.when方法。我尝试过不同的跑步者类(Mockito,JUnit4甚至是PowerMock)以及@PrepareForTest等各种注释组合,并在@Mock下声明测试之外的mockViolation。

1 个答案:

答案 0 :(得分:1)

您的语法是正确的,但您的具体问题是getRootBeanClass返回Class,而Mockito 无法模拟最终类。在引擎盖下,当你要求模拟一个类时,Mockito会生成一个子类,它(有效地)覆盖所有方法并将它们重定向到Mockito控件。这种覆盖机制是您在模拟final方法以及finaljava.lang.Class等方面遇到问题的原因。

虽然您可以通过PowerMock完成此操作,但这是不可取的,例如2011年的Johan Haleby's post from powermock@googlegroups.com

  

我认为没有可能模仿Class,因为这会搞砸很多PowerMock内部的东西。如果设置MockGateway.MOCK_GET_CLASS_METHOD = true,您可以如何模拟对象的“getClass()”方法。

     

我强烈建议[sic]反对模拟Class或getClass方法。尝试以其他方式验证它。

因为您只关心使getSimpleName返回可预测的值,请考虑创建一个新类(“MyBean”)并设置getRootBeanClass()以返回它。在界面上模拟返回值非常容易,并且您将获得与您希望使用的相同类型的简单名称返回值。