Mockito返回值基于参数的属性



通常,当使用Mockito时,我会做类似的事情:

Mockito.when(myObject.myFunction(myParameter)).thenReturn(myResult);

可以按照

的线路做某事
myParameter.setProperty("value");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("myResult");
myParameter.setProperty("otherValue");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("otherResult");

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

因此,当执行代码时,它的行为类似:

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
}

这是当前的解决方案,希望可以提出更好的建议。

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");
}

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

when(mockObject.myMethod(anyString()))
    .thenAnswer(invocation -> 
        invocation.getArgumentAt(0, String.class));

这是一种方法。这使用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;
            }});
    }
}

有一个替代语法,我实际上更喜欢,这将达到完全相同的内容。在您身上,您选择哪一个。这只是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());
}

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

有关更多详细信息,请参见Matchers的Javadoc,更具体地说是ArgumentMatcher

这是使用Mockito-Kotlin库中的Kotlin中的样子。

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

您可以使用Mockito 3.6.0:

进行此操作
when(mockObject.myMethod(anyString()))
    .thenAnswer(invocation -> myStringMethod(invocation.getArgument(0)));

此答案基于Sven的答案和Martijn Hiemstra的评论,getArgumentAt()更改为getArgument()

最新更新