Mockito - 验证集合中的对象是否称为方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mockito - 验证集合中的对象是否称为方法相关的知识,希望对你有一定的参考价值。

我正在与Mockito框架斗争:

我有一个特定类型的Set,我想验证它中的任何对象是否称为特定方法。这是我的代码:

@Mock
private Set<MyType> myTypes = (Set<MyType>) mock(Set.class);

@Before
public void setUp() throws Exception{
    TestObject testObject = spy(new TestObject());        

    for(int i = 0; i < 4; i++){        
        MyType mT = mock(MyType.class);
        mT.setName("Name"+i);
        myTypes.add(mT);
    }

    testObject.setMyTypesSet(myTypes);
}

@Test
public void myTypeSet_Test(){

    //call method which calls "getName()" for each element in the set        
    testObject.myTypeSet();

    //HERE IS MY STRUGGLE
    verify(myType, times(3)).getName();
}

所以myTypes对象有一个名为getName()的方法。我想测试,如果方法getName()在我测试的方法中被调用了3次。我不能写verify(myTypes, times(3)).getName()因为Set没有方法getName()。我希望我说清楚。

答案

您可以简单地在Set的每个模拟元素上调用验证:

for (MyType myType : myTypes) {
    verify(myType, times(3))
    .getName();
}

但这不适用于实际代码,因为myTypes被定义为Mock

@Mock
private Set<MyType> myTypes = (Set<MyType>) mock(Set.class);

而且你没有记录任何行为。 所以你永远不能迭代添加的元素,因为你不会在Set中添加元素:

MyType mT = Mockito.mock(MyType.class);
mT.setName("Name" + i);
myTypes.add(mT);

事实上myTypes不是一个模仿者。 将其声明为普通对象:

private Set<MyType> myTypes = new HashSet<>();

您也不需要监视被测对象。 您想要验证invocation of mocks,而不是要测试的对象的调用。

所以你也可以替换:

TestObject testObject = Mockito.spy(new TestObject());

通过:

TestObject testObject = new TestObject();

请注意,间谍活动不是一种好习惯,而是一种解决方法。因此,尽可能避免这种情况,因为您不需要它!

它应该没问题。

另一答案

你不需要在这里嘲笑Set;有一个充满嘲笑的常规Set应该是足够的:

private Set<MyType> myTypes = new HashSet<>();

然后

for(MyType myType : myTypes) {
  verify(myType, times(3)).getName();
}

假设你实际上为每个元素调用了getName() 3次。如果情况并非如此,并且您只是为每个调用一次,那么它将是times(1)

另一答案

验证是否在每个对象上调用了getName方法3次

for(MyType myType : myTypes) {
  verify(myType, times(3)).getName();
}

验证在任何对象上总共调用了getName方法3次

public class MyTypeTest {

  @Mock private Set<MyType> myTypes = new HashSet<>();

  @Before
  public void setUp() throws Exception{
    TestObject testObject = spy(new TestObject());

    for(int i = 0; i < 4; i++){
      MyType mT = Mockito.mock(MyType.class);
      mT.setName("Name"+i);
      myTypes.add(mT);
    }

    testObject.setMyTypesSet(myTypes);
  }

  @Test
  public void myTypeSet_Test(){

    //call method which calls "getName()" for each element in the set
    testObject.myTypeSet();

    int numberOfCalls = 0;
    for(MyType myTypeMock : myTypes) {
      Collection<Invocation> invocations = Mockito.mockingDetails(myTypeMock).getInvocations();
      numberOfCalls += invocations.size();
    }

    assertEquals(3, numberOfCalls)
  }


}

class MyType {
  private String name;
  public void setName(String n) { name = n;}
  public String getName() {return name};
}

以上是关于Mockito - 验证集合中的对象是否称为方法的主要内容,如果未能解决你的问题,请参考以下文章

称为验证的 Mockito Kotlin 单元测试方法抛出空指针异常

是否可以以紧凑的方式使用 Mockito 验证任意交互?

学习单元测试 Mockito 一篇文章就够了

Mockito - 验证对象根本没有被调用

Mockito的参数匹配

Mockito验证只调用了一个预期的方法