Aleksei Golubev
Aleksei Golubev

Reputation: 352

Create an array of mocks using Mockito

I'm trying to make a separate method for creating a list of mocks. E.g. we have a class Entity:

class Entity {
    public List<SubEntity> subEntities;
}

But SubEntity is interface which has two implementations:

class SubEntityA implements SubEntity {
    public SomeType someProp;
}

and

class SubEntityB implements SubEntity {
    public SomeAnotherType someAnotherProp;
}

so I can have in subEnities property a mixed list of SubEntityA and SubEntityB objects.

In real case I have more then two types and I'd like to write a test where I need to generate a different amount of mocks of this classes and add it to the property subEntities. I can easily crate one mock using:

mock(SubEntityA.class)

but when I'm trying to do something like this:

private List<SubEntity> getMocks(Class<? extends SubEntity> classToMock, int amount) {
    List<SubEntity> mocks = new ArrayList<>();
    for (int i = 0; i < amount; i++) {
        mocks.add(mock(classToMock));
    }
    return mocks;
}

I get into trouble using e.g. List<SubEntityA> list = getMocks(SubEntityA.class, 3), because SubEntityA.class or SubEntityB.class couldn't be casted to Class<? extends SubEntity>.

What I'm doing wrong? What shall I do to pass classes properly? I tried to find Mockito's methods but found only Mockito.anyListOf. As I understood It won't work in my case.

Thanks!

[UPD] The test looks like:

@Mock
private RepoSubA repoA;

@Mock
private RepoSubB repoB;

@Mock
private Repo repo;

@InjectMocks    
private LogicBean testee;

@Test
public void test() {
    //given
    List<SubEntityA> listA = getMocks(SubEntityA.class, 3);
    List<SubEntityB> listB = getMocks(SubEntityB.class, 3);
    List<SubEntity> list = new ArraList<>();
    list.addAll(listA);
    list.addAll(listB);

    Rule rule = someFixture();
    when(repoA.getA(rule.getId())).thenReturn(listA);
    when(repoB.getB(rule.getId())).thenReturn(listB);

    //when
    List<SubEntity> result = testee.someMagic(rule);

    //then
    assertThat(result, hasSize(list.size());
}

Upvotes: 2

Views: 3569

Answers (2)

Andrei Makarevich
Andrei Makarevich

Reputation: 444

Following is more strict and consistent as you use just the same class for return list type.

private static <T extends SubEntity> List<T> getMocks(Class<T> classToMock, int amount) {
    List<T> mocks = new ArrayList<>();
    for (int i = 0; i < amount; i++) {
        mocks.add(mock(classToMock));
    }
    return mocks;
}

Upvotes: 1

Jose Martinez
Jose Martinez

Reputation: 12022

I tried to get the error but failed. This is the code I wrote.

public static class Entity {

    public List<SubEntity> subEntities;
}

public static class SubEntityA implements SubEntity {

}

public static class SubEntityB implements SubEntity {

}

private List<? extends SubEntity> getMocks(Class<? extends SubEntity> classToMock, int amount) {
    List<SubEntity> mocks = new ArrayList<>();
    for (int i = 0; i < amount; i++) {
        mocks.add(mock(classToMock));
    }
    return mocks;
}

@Test
public void test(){
    assertEquals(3, getMocks(SubEntityA.class, 3).size());
    List<SubEntityA> mocks = (List<SubEntityA>) getMocks(SubEntityA.class, 3);
    assertEquals(3, getMocks(SubEntityB.class, 3).size());
}

I then executed Junit on the test method. The test passed.

EDIT: To respond to your comment, you can change the signature of your getmocks method so that the output could be cast to List<SubEntityA>. I edited my code above and the cast works.

Upvotes: 1

Related Questions