Java mockito 基于参数属性的返回值

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

mockito return value based on property of a parameter

javamockito

提问by BevynQ

Normally when using mockito I will do something like

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

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

Is it possible to do something along the lines of

是否有可能按照以下方式做一些事情

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

myParameter.setProperty("otherValue");
Mockito.when(myObject.myFunction(myParameter)).thenReturn("otherResult");

So rather than when just using the parameter to determine the result. It is using a value of a property inside the parameter to determine the result.

所以而不是仅仅使用参数来确定结果。它使用参数内的属性值来确定结果。

so when the code is executed it behaves like so

所以当代码被执行时,它的行为就像这样

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
}


current solution, hopefully something better can be suggested.

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

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

采纳答案by Dawood ibn Kareem

Here's one way of doing it. This uses an Answerobject to check the value of the property.

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

There's an alternative syntax, which I actually prefer, which will achieve exactly the same thing. Over to you which one of these you choose. This is just the setUpmethod - the rest of the test class should be the same as above.

有一种替代语法,我实际上更喜欢它,它可以实现完全相同的效果。由您决定选择其中的哪一个。这只是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());
}

回答by fge

Yes you can, using a custom argument matcher.

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

See the javadoc of Matchersfor more details, and more specifically ArgumentMatcher.

有关更多详细信息,更具体地说,请参阅的 javadocMatchersArgumentMatcher

回答by Sven

In Java 8 it is even simpler than all of the above:

在 Java 8 中,它甚至比以上所有更简单:

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

回答by tasomaniac

Here is how it would look like in Kotlin with mockito-kotlinlibrary.

下面是它在带有mockito-kotlin库的Kotlin 中的样子

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