Java 如何根据参数属性在 Mockito 中返回不同的值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37097293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:59:33  来源:igfitidea点击:

How to return different value in Mockito based on parameter attribute?

javamockito

提问by Roee Gavirel

The class that I test receive a client wrapper:

我测试的类接收客户端包装器:

The tested class (snippest)

被测试的类(片段)

private ClientWrapper cw
public Tested(ClientWrapper cw) {
    this.cw = cw;
}

public String get(Request request) {
    return cw.getClient().get(request);
}

The test initialization:

测试初始化​​:

ClientWrapper cw = Mockito.mock(ClientWrapper.class);
Client client = Mockito.mock(Client.class);
Mockito.when(cw.getClient()).thenReturn(client);
//Here is where I want to alternate the return value:
Mockito.when(client.get(Mockito.any(Request.class))).thenReturn("100");

In the exmaple I always return "100", but the Request have an attribute idand I would like to return different values to client.get(Request)based on the request.getId()value.

在示例中,我总是返回“100”,但请求有一个属性id,我想client.get(Request)根据该request.getId()值返回不同的值。

How can I do it?

我该怎么做?

采纳答案by Adam Siemion

You can use Mockito's answers, so instead of:

您可以使用 Mockito 的答案,而不是:

Mockito.when(client.get(Mockito.any(Request.class))).thenReturn("100");

write:

写:

Mockito.when(client.get(Mockito.any(Request.class)))
 .thenAnswer(new Answer() {
   Object answer(InvocationOnMock invocation) {
     Object[] args = invocation.getArguments();
     Object mock = invocation.getMock();
     return "called with arguments: " + args;
   }
});

回答by John Montgomery

You could create an ArgumentMatcherto let you match the Requestby id.

您可以创建一个ArgumentMatcher让您匹配Requestby id。

So the argument matcher would be like this:

所以参数匹配器会是这样的:

import org.mockito.ArgumentMatcher;

导入 org.mockito.ArgumentMatcher;

public class IsRequestWithId implements ArgumentMatcher<Request> {
    private final int id;

    public IsRequestWithId(int id) {
        this.id = id;
    }

    @Override
    public boolean matches(Object arg) {
        Request request = (Request)arg;
        return id == request.getId();
    }
}

Then you could use it like:

然后你可以像这样使用它:

Mockito.when(client.get(Mockito.argThat(new IsRequestWithId(1)))).thenReturn("100");
Mockito.when(client.get(Mockito.argThat(new IsRequestWithId(2)))).thenReturn("200");

Otherwise using an Answerwould also work, but using an ArgumentMatcherlets you keep the code more "declarative".

否则使用 anAnswer也可以,但使用 anArgumentMatcher可以让代码更具“声明性”。

回答by magiccrafter

In order to do it right and with minimal code you have to use the ArgumentMatcher, lambda expression & don't forgetto do a null check on the filters members in the ArgumentMatcherlambda (especially if you have more than one mock with the same ArgumentMatcher).

为了正确地使用最少的代码,您必须使用ArgumentMatcher, lambda 表达式并且不要忘记ArgumentMatcherlambda 中的过滤器成员进行空检查(特别是如果您有多个具有相同 的模拟ArgumentMatcher)。

Customized argument matcher:

自定义参数匹配器:

private ArgumentMatcher<Request> matchRequestId(final String target) {
    return request -> request != null &&
            target.equals(request.getId());
}

Usage:

用法:

 given(client.get(argThat(matchRequestId("1")))).willReturn("100");
 given(client.get(argThat(matchRequestId("2")))).willReturn("200");