用mockito验证对象属性值

我有一个方法调用,我想用mockito模拟。首先,我已经创建并注入了一个对象的实例,该方法将在其上被调用。我的目的是验证方法调用中的一个对象。

是否有一种方法,mockito允许您断言或验证对象和它的属性时,mock方法被调用?

例子

Mockito.verify(mockedObject)
.someMethodOnMockedObject(
Mockito.<SomeObjectAsArgument>anyObject())

而不是做anyObject(),我想检查参数对象包含一些特定的字段

Mockito.verify(mockedObject)
.someMethodOnMockedObject(
Mockito.<SomeObjectAsArgument>**compareWithThisObject()**)
248853 次浏览

添加到Mockito的新功能使这更容易,

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

看看Mockito 文档


如果有多个参数,并且只需要捕获单个参数,则使用其他ArgumentMatchers来包装其余的参数:

verify(mock).doSomething(eq(someValue), eq(someOtherValue), argument.capture());
assertEquals("John", argument.getValue().getName());

还有一种可能,如果你不想使用ArgumentCaptor(例如,因为你也在使用存根),是将Hamcrest Matchers与Mockito结合使用。

import org.mockito.Mockito
import org.hamcrest.Matchers
...


Mockito.verify(mockedObject).someMethodOnMockedObject(MockitoHamcrest.argThat(
Matchers.<SomeObjectAsArgument>hasProperty("propertyName", desiredValue)));

我认为验证参数对象最简单的方法是使用refEq方法:

Mockito.verify(mockedObject).someMethodOnMockedObject(ArgumentMatchers.refEq(objectToCompareWith));

即使对象没有实现equals(),也可以使用它,因为使用了反射。如果不想比较某些字段,只需将它们的名称作为refEq的参数。

这是基于来自iraSenthil的回答但带有注释(捕获者)的答案。在我看来,它有一些优点:

  • 它是短的
  • 这样更容易阅读
  • 它可以无警告地处理泛型

例子:

@RunWith(MockitoJUnitRunner.class)
public class SomeTest{


@Captor
private ArgumentCaptor<List<SomeType>> captor;


//...


@Test
public void shouldTestArgsVals() {
//...
verify(mockedObject).someMethodOnMockedObject(captor.capture());


assertThat(captor.getValue().getXXX(), is("expected"));
}
}

如果使用Java 8,可以使用Lambda表达式进行匹配。

import java.util.Optional;
import java.util.function.Predicate;


import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;


public class LambdaMatcher<T> extends BaseMatcher<T>
{
private final Predicate<T> matcher;
private final Optional<String> description;


public LambdaMatcher(Predicate<T> matcher)
{
this(matcher, null);
}


public LambdaMatcher(Predicate<T> matcher, String description)
{
this.matcher = matcher;
this.description = Optional.ofNullable(description);
}


@SuppressWarnings("unchecked")
@Override
public boolean matches(Object argument)
{
return matcher.test((T) argument);
}


@Override
public void describeTo(Description description)
{
this.description.ifPresent(description::appendText);
}
}

示例调用

@Test
public void canFindEmployee()
{
Employee employee = new Employee("John");
company.addEmployee(employee);


verify(mockedDal).registerEmployee(argThat(new LambdaMatcher<>(e -> e.getName()
.equals(employee.getName()))));
}

更多信息:http://source.coveo.com/2014/10/01/java8-mockito/

你可以参考以下资料:

Mockito.verify(mockedObject).someMethodOnMockedObject(eq(desiredObject))

这将验证是否以desiredObject作为参数调用mockedObject方法。

以上的解决方案在我的案例中并不适用。我不能使用ArgumentCaptor方法被调用了几次,我需要验证每一个。一个简单的使用“argThat”的Matcher很容易做到这一点。

定制的匹配器

// custom matcher
private class PolygonMatcher extends ArgumentMatcher<PolygonOptions> {
private int fillColor;
public PolygonMatcher(int fillColor) {
this.fillColor = fillColor;
}


@Override
public boolean matches(Object argument) {
if (!(argument instanceof PolygonOptions)) return false;
PolygonOptions arg = (PolygonOptions)argument;
return Color.red(arg.getFillColor()) == Color.red(fillColor)
&& Color.green(arg.getFillColor()) == Color.green(fillColor)
&& Color.blue(arg.getFillColor()) == Color.blue(fillColor);
}
}

测试运行器

// do setup work setup
// 3 light green polygons
int green = getContext().getResources().getColor(R.color.dmb_rx_bucket1);
verify(map, times(3)).addPolygon(argThat(new PolygonMatcher(green)));


// 1 medium yellow polygons
int yellow = getContext().getResources().getColor(R.color.dmb_rx_bucket4);
verify(map, times(1)).addPolygon(argThat(new PolygonMatcher(yellow)));


// 3 red polygons
int orange = getContext().getResources().getColor(R.color.dmb_rx_bucket5);
verify(map, times(3)).addPolygon(argThat(new PolygonMatcher(orange)));


// 2 red polygons
int red = getContext().getResources().getColor(R.color.dmb_rx_bucket7);
verify(map, times(2)).addPolygon(argThat(new PolygonMatcher(red)));

com.nhaarman.mockito_kotlin和非常好的和干净的koltin溶液

verify(mock).execute(argThat {
this.param = expected
})

另一个简单的方法是:

import org.mockito.BDDMockito;
import static org.mockito.Matchers.argThat;
import org.mockito.ArgumentMatcher;


BDDMockito.verify(mockedObject)
.someMethodOnMockedObject(argThat(new ArgumentMatcher<TypeOfMethodArg>() {


@Override
public boolean matches(Object argument) {
final TypeOfMethodArg castedArg = (TypeOfMethodArg) argument;


// Make your verifications and return a boolean to say if it matches or not
boolean isArgMarching = true;


return isArgMarching;
}
}));

一个简化的解决方案,无需创建一个新的Matcher实现类并使用lambda表达式:

verify(mockObject).someMockMethod(
argThat((SomeArgument arg) -> arg.fieldToMatch.equals(expectedFieldValue)));

我一直在用方法实例化模拟服务类的设置中工作。如果我想验证一个方法已经被调用了1次,对象参数在字段中包含一个特定的值,下面是我如何使用class Service方法updateMethod(UpdateObject updateObjectParam){}来执行它:

@Mock
Service service;


...


Mockito.verify(service, times(1)).updateMethod(argThat(updateParamObject -> updateParamObject.getField().equals("fieldValue")));