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

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

例子

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

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

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

当前回答

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

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

例子:

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

其他回答

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

@Mock
Service service;

...

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

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

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

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

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

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

例子:

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

refEq的javadoc提到了相等性检查是浅的!你可以在下面的链接找到更多的细节:

https://static.javadoc.io/org.mockito/mockito-core/2.2.29/org/mockito/ArgumentMatchers.html refEq (T) % 20以…)

当你使用其他没有实现.equals()方法的类时,“浅相等”问题无法控制,“DefaultMongoTypeMapper”类就是一个没有实现.equals()方法的例子。

support提供了一种方法,可以生成bean定义,而不是创建对象的实例,并且可以使用它来摆脱比较失败。

 genericBeanDefinition(DefaultMongoTypeMapper.class)
                        .setScope(SCOPE_SINGLETON)
                        .setAutowireMode(AUTOWIRE_CONSTRUCTOR)
                        .setLazyInit(false)
                        .addConstructorArgValue(null)
                        .getBeanDefinition()

**“bean定义只是对bean的描述,而不是bean本身。 bean描述正确地实现了equals()和hashCode(),所以我们提供了一个定义,告诉spring应该如何创建一个DefaultMongoTypeMapper(),而不是创建一个新的DefaultMongoTypeMapper。”

在你的例子中,你可以这样做

Mockito.verify(mockedObject)
       .doSoething(genericBeanDefinition(YourClass.class).setA("a")
       .getBeanDefinition());

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