Java Mockito 允许设置模拟返回值

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

Mockito allow mocked return value to be set

javamockito

提问by well_i

Is it possible to change the value that is returned from a mocked object?

是否可以更改从模拟对象返回的值?

Below is an example that explains what I am trying to do.

下面是一个示例,解释了我正在尝试做的事情。

public class MyClass{
  public void method(Mock obj){
    if(obj.getValue.equals("value"){
      obj.setValue("changedValue");
    }

    anotherObj.call(obj.getValue());
  }

So the above class is very simplified. It will change the value returned if the value passed in equals value.

所以上面的类非常简化。如果传入的值等于 value,它将更改返回的值。

@Test
public void test(){
  Mock obj = mock(Mock.class);
  when(obj.getValue()).thenReturn("value");

  testClass.method(obj);

  verify(anotherObj, times(1)).call("changedValue");
}

The test want to verify that the anotherObj.call is called with the changed value, but since we have mocked the return value to be 'value' this will fail as 'value' is returned.

该测试想要验证是否使用更改后的值调用 anotherObj.call,但由于我们将返回值模拟为 'value',这将在返回 'value' 时失败。

Is it possible to create a test using a mocked returnValue?

是否可以使用模拟的 returnValue 创建测试?

采纳答案by Morfic

Johnatan is right. If objis not a complex object, you can avoid mocking it and use a real one.

乔纳坦是对的。如果obj不是一个复杂的对象,您可以避免模拟它并使用真实的对象。

If for some reason this is not possible, mockito allows to define a series of answers, eg: when(obj.getValue()).thenReturn("value").thenReturn("modifiedValue");which could be what you are looking for.

如果由于某种原因这是不可能的,mockito 允许定义一系列答案,例如:when(obj.getValue()).thenReturn("value").thenReturn("modifiedValue");这可能是您正在寻找的。

Although it might be overkill, just to make sure that all was ok, I would also verify(obj).setValue("changedValue");and verify(obj, times(2)).getValue();

虽然这可能有点矫枉过正,只是为了确保一切正常,我也会verify(obj).setValue("changedValue");verify(obj, times(2)).getValue();

回答by Jonathan

Instead of mocking obj, why not use the actual implementation? Then presumably the setValueand getValuemethods would work as you would expect.

而不是嘲笑obj,为什么不使用实际实现?那么大概setValuegetValue方法会按您的预期工作。

Although I appreciate this might not be possible, as you have mentioned your example is a much simplified version of your actual problem.

虽然我很欣赏这可能是不可能的,但正如您所提到的,您的示例是您实际问题的简化版本。

回答by Michael Wiles

Would this suffice?

这样就够了吗?

    ObjectUnderTest objectUnderTest = new ObjectUnderTest();
    ObjectUnderTest spy2 = Mockito.spy(objectUnderTest);

    when(spy2.getValue()).thenAnswer(new Answer<String>() {

        @Override
        public String answer(InvocationOnMock invocation) throws Throwable {
            Object realAnswer = invocation.callRealMethod();
            if (realAnswer.equals("SOME VALUE")) {
                return "SOME OTHER VALUE";
            }else {
                return realAnswer;
            }
        }
    });

So when the real getValue returns some value you can replace that with a different value...

因此,当真正的 getValue 返回某个值时,您可以将其替换为不同的值...

回答by Michael Kretinin

Try this:

尝试这个:

@Test
public void test(){
  Mock obj = mock(Mock.class);

  doCallRealMethod().when(obj).setValue(any(String.class));
  when(obj.getValue()).thenCallRealMethod();
  obj.setValue("value");

  testClass.method(obj);

  verify(anotherObj, times(1)).call("changedValue");
}