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

时间:2017-12-18 14:27:30

标签: java unit-testing junit set 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()。我希望我说清楚。

3 个答案:

答案 0 :(得分:1)

你不需要在这里嘲笑Set;定期Set充满嘲讽就足够了:

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

然后

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

假设您实际为每个设置元素调用getName() 3次。如果情况并非如此,并且您只是为每个调用一次,则会times(1)而是

答案 1 :(得分:0)

验证是否在每个对象上调用了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};
}

答案 2 :(得分:0)

您只需在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());

by:

TestObject testObject = new TestObject();

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

应该没事。