如何在Java中为单元测试模拟通用参数?

时间:2018-10-31 11:28:51

标签: java generics junit mockito powermock

我想模拟外部服务的功能签名。

public <T> void save(T item, AnotherClass anotherClassObject);

给出此函数签名和类名IGenericService,如何用PowerMock模拟它? 还是Mockito?

对于这种泛型,我正在使用:Theodore中的T类T item。例如,我尝试使用:

doNothing().when(iGenericServiceMock.save(any(Theodore.class),
                    any(AnotherClass.class));

IntelliJ将其启动:

save(T, AnotherClass) cannot be applied to 
(org.Hamcrest.Matcher<Theodore>, org.Hamcrest.Matcher<AnotherClass>)

它引用了以下原因:

reason: No instance(s) of type variable T exist 
so that Matcher<T> conforms to AnotherClass

首先,应该解决通用参数是否得到正确处理的问题。在这种情况下,人们可以做些什么?

更新:作为ETO共享:

doNothing().when(mockedObject).methodToMock(argMatcher); 

有着相同的命运。

3 个答案:

答案 0 :(得分:2)

尝试使用Mockito的ArgumentMatcher。同样在when中仅放置模拟的引用:

doReturn(null).when(iGenericServiceMock).save(
    ArgumentMatchers.<Theodore>any(), ArgumentMatchers.any(AnotherClass.class));

答案 1 :(得分:2)

您将错误的参数传递给when。可能有些混乱,但是when方法有两种不同的用法(实际上是两种不同的方法):

  1. when(mockedObject.methodYouWantToMock(expectedParameter, orYourMatcher)).thenReturn(objectToReturn);
    
  2. doReturn(objectToReturn).when(mockedObject).methodYouWantToMock(expectedParameter, orYourMatcher);
    

注意:在两种情况下都请注意when方法的输入参数

在您的特定情况下,您可以执行以下操作:

doReturn(null).when(iGenericServiceMock).save(any(Theodore.class), any(AnotherClass.class));

这将解决您的编译问题。但是,由于使用org.mockito.exceptions.misusing.CannotStubVoidMethodWithReturnValue的方法试图返回某些内容(void不是null),因此使用void时测试将失败。您应该做的是:

doNothing().when(iGenericServiceMock).save(any(Theodore.class), any(AnotherClass.class));

稍后,您可以使用verify方法检查与模拟对象的互动。

更新:

检查您的进口。您应该使用org.mockito.Matchers.any而不是org.hamcrest.Matchers.any

答案 2 :(得分:1)

好而迅速的答案!我终于用下面的代码使它变得更加平滑:

doNothing().when(iGenericServiceMock).save(Mockito.any(), Mockito.any()); 

直到我将Mockito置于Intellij再次对其感到高兴的任何方法之前。