本文介绍了MockitoException-是* void方法*,并且*不能*使用*返回值*!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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的交互(这似乎是一个模拟),将whenthenReturn视为与最近的模拟调用相对应,并错误地告诉您您正在使用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方法*,并且*不能*使用*返回值*!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 05:35