问题描述
我正在使用Mockito进行单元测试,并且遇到了以下异常.
I'm using Mockito for unit testingand I'm getting the following exception.
org.mockito.exceptions.base.MockitoException:
`'setResponseTimeStampUtc'` is a *void method* and it *cannot* be stubbed with a *return value*!
Voids are usually stubbed with Throwables:
doThrow(exception).when(mock).someVoidMethod();
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. The method you are trying to stub is *overloaded*. Make sure you are calling the right overloaded version.
2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not verify/stub final methods.
3. A spy is stubbed using `when(spy.foo()).then()` syntax. It is safer to stub spies -
- with `doReturn|Throw()` family of methods. More in javadocs for Mockito.spy() method.
这是实际的课程
@Repository
public class CardRepositoryImpl implements ICardRepository {
@Autowired
private OperationBean operation;
@Override
public OperationBean getCardOperation(final String cardHolderId, final String requestTimeStamp) {
operation.setRequestTimeStampUtc(requestTimeStamp);
operation.setResponseTimeStampUtc(DateUtil.getUTCDate());
return operation;
}
}
这是我编写的Test类.
this is the Test class I have written.
@RunWith(MockitoJUnitRunner.class)
public class CardRepositoryImplUnitTestFixture_Mockito {
@InjectMocks
private CardRepositoryImpl cardRepositoryImpl;
private OperationBean operationBean;
@Before
public void beforeTest() {
MockitoAnnotations.initMocks(this);
}
@Test
public void canGetCardOperation(){
when(cardRepositoryImpl.getCardOperation("2", Mockito.anyString())).thenReturn(operationBean);
}
}
由于format()方法是最终方法,因此return语句是否存在此问题.
Is this an issue with the return statement since format() method is a final method.
public static String getUTCDate() {
final TimeZone timeZone = TimeZone.getTimeZone("UTC");
final Calendar calendar = Calendar.getInstance(timeZone);
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd'T'HH:mm:ss.SSS'Z'");
simpleDateFormat.setTimeZone(timeZone);
return simpleDateFormat.format(calendar.getTime());
}
我该如何解决?
推荐答案
@InjectMocks
private CardRepositoryImpl cardRepositoryImpl;
when(cardRepositoryImpl.getCardOperation("2", Mockito.anyString()))
.thenReturn(operationBean);
cardRepositoryImpl
不是一个模拟,因此您不能对其进行存根.使用@InjectMocks
指示Mockito构造一个真实的CardRepositoryImpl,并用测试用例上的字段替换其私有字段和构造函数参数.您可能想改用间谍;一秒钟即可获得更多信息.
cardRepositoryImpl
is not a mock, so you can't stub it. With @InjectMocks
you are instructing Mockito to construct a real CardRepositoryImpl and have its private fields and constructor parameters substituted with fields on the test case. You'll probably want to use a spy instead; more on that in a second.
但是首先,为什么会出现该错误消息?因为它不是模拟,所以对cardRepositoryImpl.getCardOperation
的调用发生在实际的CardRepositoryImpl实例上. Mockito看到与operationBean
的交互(这似乎是一个模拟),将when
和thenReturn
视为与最近的模拟调用相对应,并错误地告诉您您正在使用void方法(重要的是, 错误方法),并返回一个值.
But first, why that error message? Because it's not a mock, the call to cardRepositoryImpl.getCardOperation
happens on an actual CardRepositoryImpl instance. Mockito sees the interactions with operationBean
(which does seem to be a mock), treats the when
and thenReturn
as corresponding with that most recent mock call, and erroneously tells you you're stubbing a void method (importantly, the wrong method) with a return value.
在测试CardRepositoryImpl时,您不应嘲笑CardRepositoryImpl,也不应对其进行存根以返回值:除了Mockito可以工作之外,它不会进行任何测试.您可能应该重新考虑所需的内容进行存根以便您的测试正常工作.
In a test for CardRepositoryImpl, you shouldn't be mocking CardRepositoryImpl, nor stubbing it to return values: This won't test anything, except that Mockito works. You should probably rethink what you need to stub in order for your test to work.
但是,当存根一个方法时,您可能想要存根同一类中的另一个方法.这可以通过间谍来完成:
However, when stubbing one method, you might want to stub another method in the same class. This can be accomplished with a spy:
@Test
public void canGetCardOperation(){
CardRepositoryImpl spyImpl = spy(cardRepositoryImpl);
when(spyImpl.getCardOperation(Mockito.eq("2"), Mockito.anyString()))
.thenReturn(returnValue);
// ...
spyImpl.someOtherMethod(); // Any matching calls to getCardOperation from
// someOtherMethod will use the stub above.
}
侧面说明:存根时,您将相邻使用anyString
和"2"
.当使用像anyString
这样的Matchers时,如果将它们用作所有自变量,则需要将其用于所有自变量. 在此处查看更多信息.
Side note: You use anyString
and "2"
adjacently while stubbing. When using Matchers like anyString
, you need to use them for all arguments if you use them for any arguments at all. See more here.
这篇关于MockitoException-是* void方法*,并且*不能*使用*返回值*!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!