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

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

例子

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

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

Mockito.verify(mockedObject)
       .someMethodOnMockedObject(
              Mockito.<SomeObjectAsArgument>**compareWithThisObject()**)

当前回答

如果使用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/

其他回答

非常干净的koltin溶液来自com.nhaarman.mockito_kotlin

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

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

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

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

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

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

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

@Mock
Service service;

...

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

添加到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());