2

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());
}
5
  • 1
    getMocks(SubEntityA.class, amount) will perfectly compile. Besides, you don't perform any cast in your code. Please share the full stracktrace. Commented Feb 6, 2018 at 17:38
  • @davidxxx There's just one error: Error:(101, 84) java: incompatible types: java.util.List<model.SubEntity> cannot be converted to java.util.List<model.SubEntotyA> Commented Feb 6, 2018 at 17:48
  • Unfortunately, I should create different lists for each type and then add them to subEntities. Commented Feb 6, 2018 at 17:54
  • Since SubEntity is an interface, why does it matter the actual type? Is there some instanceof/casting going on which is making testing harder? Commented Feb 6, 2018 at 18:23
  • Yes, It matters, because I also need to mock results of repositories. Commented Feb 6, 2018 at 18:39

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

There are troubles with casting from List<SubEntity> to List<SubEntityA> list. The result of getMocks(...) should be set to when(repo.getEntitiesA()).thenReturn(list).
I used the code in your question. Was there more code that you did not include? If so, can you please include that code and be specific as to where the error is occurring.
Thanks for comment, I've provided example of test in question.
It works! Now the test could be much more pretty! Thank you for your help!
1

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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.