mockito返回值基于参数的属性

Bev*_*ynQ 53 java mockito

通常在使用mockito时我会做类似的事情

Mockito.when(myObject.myFunction(myParameter)).thenReturn(myResult);
Run Code Online (Sandbox Code Playgroud)

是否有可能做一些事情

myParameter.setProperty("value");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("myResult");

myParameter.setProperty("otherValue");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("otherResult");
Run Code Online (Sandbox Code Playgroud)

因此,而不是仅仅使用参数来确定结果.它使用参数内的属性值来确定结果.

因此,当代码执行时,它的行为就像这样

public void myTestMethod(MyParameter myParameter,MyObject myObject){
    myParameter.setProperty("value");
    System.out.println(myObject.myFunction(myParameter));// outputs myResult

    myParameter.setProperty("otherValue");
    System.out.println(myObject.myFunction(myParameter));// outputs otherResult
}
Run Code Online (Sandbox Code Playgroud)

目前的解决方案,希望能提出更好的建议.

private class MyObjectMatcher extends ArgumentMatcher<MyObject> {

    private final String compareValue;

    public ApplicationContextMatcher(String compareValue) {
        this.compareValue= compareValue;
    }

    @Override
    public boolean matches(Object argument) {
        MyObject item= (MyObject) argument;
        if(compareValue!= null){
            if (item != null) {
                return compareValue.equals(item.getMyParameter());
            }
        }else {
            return item == null || item.getMyParameter() == null;
        }
        return false;
    }
}

public void initMock(MyObject myObject){
    MyObjectMatcher valueMatcher = new MyObjectMatcher("value");
    MyObjectMatcher otherValueMatcher = new MyObjectMatcher("otherValue");
    Mockito.when(myObject.myFunction(Matchers.argThat(valueMatcher))).thenReturn("myResult");
    Mockito.when(myObject.myFunction(Matchers.argThat(otherValueMatcher))).thenReturn("otherResult");
}
Run Code Online (Sandbox Code Playgroud)

Sve*_*ven 54

在Java 8中,它比上述所有内容更简单:

when(mockObject.myMethod(anyString()))
    .thenAnswer(invocation -> 
        invocation.getArgumentAt(0, String.class));
Run Code Online (Sandbox Code Playgroud)

  • 您可以通过使lambda更大来区分不同的参数.只需添加一个if来选择写入.它可以是这样的:`invocation-> {String param = invocation.getArgumentAt(0,String.class); if(param.equals("value"))返回"myResultOnValue"; if(param.equals("otherParam")返回"myResultOnOtherValue",否则返回"MyDefaultResult"; (8认同)
  • 不再需要定义类型。这更简单: when(mockObject.myMethod (anyString() ) ).thenAnswer(invocation -&gt; invocation.getArgument(0)); (5认同)
  • 我喜欢这个想法,但似乎不完整?这如何区分"值"和"otherValue"并在每种情况下返回不同的答案? (4认同)

Daw*_*ica 36

这是一种做法.这使用一个Answer对象来检查属性的值.

@RunWith(MockitoJUnitRunner.class)
public class MyTestClass {
    private String theProperty;
    @Mock private MyClass mockObject;

    @Before
    public void setUp() {
        when(mockObject.myMethod(anyString())).thenAnswer(
            new Answer<String>(){
            @Override
            public String answer(InvocationOnMock invocation){
                if ("value".equals(theProperty)){
                    return "result";
                }
                else if("otherValue".equals(theProperty)) {
                    return "otherResult";
                }
                return theProperty;
            }});
    }
}
Run Code Online (Sandbox Code Playgroud)

有一种替代语法,我实际上更喜欢它,它将实现完全相同的东西.在你的选择中选择哪一个.这只是setUp方法 - 测试类的其余部分应与上面相同.

@Before
public void setUp() {
    doAnswer(new Answer<String>(){
        @Override
        public String answer(InvocationOnMock invocation){
            if ("value".equals(theProperty)){
                return "result";
            }
            else if("otherValue".equals(theProperty)) {
                return "otherResult";
            }
            return theProperty;
        }}).when(mockObject).myMethod(anyString());
}
Run Code Online (Sandbox Code Playgroud)

  • 您提供的解决方案不允许根据模拟方法的不同参数模拟响应。在这种情况下,如果我们想根据mockObject.myMethod(String argument);的参数返回不同的响应;如果在测试运行时,如果“参数”是“值”,则返回此值,如果“参数”是“其他值”,则返回其他值。 (3认同)

fge*_*fge 6

是的,您可以使用自定义参数匹配器.

有关更多详细信息,请参阅javadocMatchers,更具体地说ArgumentMatcher.


tas*_*iac 6

这是在 Kotlin 中使用mockito-kotlin库的样子。

mock<Resources> {
    on {
        mockObject.myMethod(any())
    } doAnswer {
        "Here is the value: ${it.arguments[0]}"
    }
}
Run Code Online (Sandbox Code Playgroud)