Java 用不同的参数模拟相同的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41767496/
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 23:39:49  来源:igfitidea点击:

Mock same method with different parameters

javaunit-testingjunitmockito

提问by Zeeshan Bilal

I am using mockito to test my business service, and it uses a utility that i want to mock. there are at least 2-3 calls in each service method for utility with different arguments.

我正在使用 mockito 来测试我的业务服务,它使用了我想要模拟的实用程序。对于具有不同参数的实用程序,每个服务方法中至少有 2-3 次调用。

Is there any recommended way to use multiple when(...).thenReturn(...)for same method but different arguments?

是否有任何推荐的方法可以when(...).thenReturn(...)对相同的方法但不同的参数使用多个?

I also want to use any()marcher as well inside. Is it possible?

我也想在any()里面使用marcher。是否可以?

Update: sample code.

更新:示例代码。

@Test
public void myTest() {
  when(service.foo(any(), new ARequest(1, "A"))).thenReturn(new AResponse(1, "passed"));
  when(service.foo(any(), new ARequest(2, "2A"))).thenReturn(new AResponse(2, "passed"));
  when(service.foo(any(), new BRequest(1, "B"))).thenReturn(new BResponse(112, "passed"));

  c.execute();
}

public class ClassUnderTest {
  Service service = new Service();
  public void execute() {
    AResponse ar = (AResponse) service.foo("A1", new ARequest(1, "A"));
    AResponse ar2 = (AResponse) service.foo("A2", new ARequest(2, "2A"));
    BResponse br = (BResponse) service.foo("B1", new BRequest(1, "B"));
  }
}

public class Service {
  public Object foo(String firstArgument, Object obj) {
    return null; //return something
  }
}

采纳答案by Nicolas Filotto

One way could be to avoid being too restrictive on your arguments in order to provide all the expected results with only one thenReturncall.

一种方法是避免对您的论点过于严格,以便仅通过一次thenReturn调用即可提供所有预期结果。

For example let's say that I want to mock this method:

例如,假设我想模拟这个方法:

public String foo(String firstArgument, Object obj) {
    return "Something";
}

You could then mock it by providing as many results as you want like below:

然后,您可以通过提供任意数量的结果来模拟它,如下所示:

// Mock the call of foo of any String to provide 3 results
when(mock.foo(anyString(), anyObject())).thenReturn("val1", "val2", "val3");

Calls to foowith any parameters will provide respectively "val1", "val2", then any subsequent calls will provide "val3".

foo带有任何参数的调用将分别提供“ val1”、“ val2”,然后任何后续调用都将提供“ val3”。



In case you do care about passed values but don't want to depend on call sequence you can use thenAnswerto provide an answer that matches with the second argument like you currently do but with 3 different thenReturn.

如果您确实关心传递的值但不想依赖于调用序列,您可以使用它thenAnswer来提供与您目前所做的第二个参数匹配但具有 3 个不同thenReturn.

when(mock.foo(anyString(), anyObject())).thenAnswer(
    invocation -> {
        Object argument = invocation.getArguments()[1];
        if (argument.equals(new ARequest(1, "A"))) {
            return new AResponse(1, "passed");
        } else if (argument.equals(new ARequest(2, "2A"))) {
            return new AResponse(2, "passed");
        } else if (argument.equals(new BRequest(1, "B"))) {
            return new BResponse(112, "passed");
        }
        throw new InvalidUseOfMatchersException(
            String.format("Argument %s does not match", argument)
        );
    }
);

回答by Tom Bulgur

I think: the "recommended" way would be the one that WORKS for you; and that comes with the least amount of coding efforts.

我认为:“推荐”的方式将是适合您的方式;这带来了最少的编码工作。

You have to have provide THOSE specifications that are necessary to make your test do what it has to do. There is no way around that.

您必须提供使您的测试完成它必须做的事情所必需的那些规范。没有办法解决这个问题。

If you really care about the arguments used, then you have to specify them accordingly. If you don't care; use any().

如果你真的关心使用的参数,那么你必须相应地指定它们。如果你不在乎;使用any().

回答by Sean Patrick Floyd

The proper way would be to match the arguments using eq(), but if you don't want to do that, you can just record multiple return values.

正确的方法是使用 匹配参数eq(),但如果您不想这样做,您可以只记录多个返回值。

when(someService.doSomething(any(SomeParam.class))).thenReturn(
  firstReturnValue, secondReturnValue, thirdReturnValue
);

Now the first call will return firstValue, the second secondValueand all following thirdValue.

现在第一个调用将返回firstValue,第二个secondValue和所有后续调用将返回thirdValue

回答by piritocle

If you are mocking the method just want to verify that the correct arguments are being passed in, you can use any() and verify with ArgumentCaptor following the mocked method call.

如果您正在模拟该方法只是想验证是否传入了正确的参数,您可以使用 any() 并在模拟方法调用之后使用 ArgumentCaptor 进行验证。