java Mockito:以复杂对象为参数的存根方法

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

Mockito: Stub method with complex object as a parameter

javaparametersmockitostub

提问by Andres_age

Maybe this is a newbie question, but can't find the answer.

也许这是一个新手问题,但找不到答案。

I need to stub a method with Mockito. If the method has "simple" arguments, then I can do it. For example, a find method with two parameters, car color and number of doors:

我需要用 Mockito 存根一个方法。如果该方法具有“简单”参数,那么我可以做到。例如,一个 find 方法有两个参数,汽车颜色和门数:

 when(carFinderMock.find(eq(Color.RED),anyInt())).thenReturn(Car1);
 when(carFinderMock.find(eq(Color.BLUE),anyInt())).thenReturn(Car2);
 when(carFinderMock.find(eq(Color.GREEN), eq(5))).thenReturn(Car3);

The problem is that the find argument is a complex object.

问题在于 find 参数是一个复杂的对象。

 mappingFilter = new MappingFilter();
 mappingFilter.setColor(eq(Color.RED));
 mappingFilter.setDoorNumber(anyInt());
 when(carFinderMock.find(mappingFilter)).thenReturn(Car1);

This code does not work. The error is "Invalid use of argument matchers! 1 matchers expected, 2 recorded".

此代码不起作用。错误是“参数匹配器的使用无效!预期有 1 个匹配器,已记录 2 个”。

Can't modify the "find" method, it needs to be a MappingFilter parameter.

不能修改“find”方法,它需要是一个MappingFilter参数。

I suppose that I have to do "something" to indicate Mockito that when the mappingFilter.getColor is RED, and mappingFilter.getDoorNumber is any, then it has to return Car1 (and the same for the other two sentences). But how?

我想我必须做“某事”来指示 Mockito,当 mappingFilter.getColor 是 RED 并且 mappingFilter.getDoorNumber 是 any 时,它必须返回 Car1(其他两个句子也是如此)。但是如何?

回答by JB Nizet

Use a Hamcrest matcher, as shown in the documentation:

使用 Hamcrest 匹配器,如文档中所示:

when(carFinderMock.find(argThat(isRed()))).thenReturn(car1);

where isRed()is defined as

其中isRed()定义为

private Matcher<MappingFilter> isRed() {
    return new BaseMatcher<MappingFilter>() {
        // TODO implement abstract methods. matches() should check that the filter is RED.
    }
}

回答by Gopi

You need to correctly implement equals()method of your MappingFilter. In equals()you should only compare color and not doorNumber.

您需要正确实现MappingFilter 的equals()方法。在equals() 中,您应该只比较颜色而不是doorNumber

In simplest form, it should look like this -

以最简单的形式,它应该是这样的——

@Override
public boolean equals(Object obj) {
    MappingFilter other = (MappingFilter) obj;
    return other.getColor() == this.getColor();
}

Also, you should form your MappingFilter simply as below instead of using any matcher such as eq

此外,您应该像下面这样简单地形成您的 MappingFilter,而不是使用任何匹配器,例如 eq

 mappingFilter = new MappingFilter();
 mappingFilter.setColor(Color.RED);
 mappingFilter.setDoorNumber(10); //Any integer

回答by ?ukasz Wachowicz

Since 2.1.0Mockito has its own matcher mechanism build on top of org.mockito.ArgumentMatcherinterface. This allows to avoid using Hamcrest. Usage is almost of same as with Hamcrest. Keep in mind that ArgumentMatcheris a functional interface and implementation of a matched can be expressed as a lambda expression.

2.1.0 开始,Mockito 在org.mockito.ArgumentMatcher界面之上建立了自己的匹配器机制。这允许避免使用 Hamcrest。用法几乎与 Hamcrest 相同。请记住,这ArgumentMatcher是一个函数式接口,匹配项的实现可以表示为 lambda 表达式。

private ArgumentMatcher<SomeObject> isYellow() {
    return argument -> argument.isYellow();
}

and then

接着

when(mock.someMethod(argThat(isYellow()).thenReturn("Hurray");