I have the following code:
@Component
public class Wrapper
{
@Resource
private List strategies;
public String getName(String
Annotate it with @Spy instead of @Mock. As Mockito cannot spy on an interface, use a concrete implementation, for example ArrayList. During test setup add the mocks to the List spy. This way you do not need to alter your test subject solely for test purposes.
@InjectMocks
private Wrapper testedObject = new Wrapper();
@Spy
private ArrayList<Strategy> mockedStrategies;
@Mock
private StrategyA strategyA;
@Mock
private StrategyB strategyB;
@Before
public void setup() throws Exception {
mockedStrategies.add(strategyA);
mockedStrategies.add(strategyB);
}
Mockito can not know that you want to put somthing in the List strategies.
You should rethink this an do something like this
@InjectMocks
private Wrapper testedObject = new Wrapper ();
private List<Strategy> mockedStrategies;
@Mock
StrategyA strategyA;
@Mock
StrategyB strategyB;
@Before
public void setup() throws Exception {
mockedStrategies = Arrays.asList(strategyA, strategyB);
wrapper.setStrategies(mockedStrategies);
}
You should not mock collections.
Create the mocks you need and put them into a list:
private List<Strategy> strategies; // not mocked!
@Mock
StrategyA strategyA;
@Mock
StrategyB strategyB;
@Before
public void setup(){
strategies= Arrays.asList(strategyA,strategyB);
testedObject.strategies= strategies;
}
@Test
public void shouldReturnNameForGivenId()
{ // irrevelant code...
//when
testedObject.getName(ID);
}
Why not just mock out your call to toStream()
?
@InjectMocks
private Wrapper testedObject = new Wrapper();
private List<Strategy> mockedStrategies;
@Mock
StrategyA strategyA;
@Mock
StrategyB strategyB;
@Before
public void setup() {
when(strategies.stream()).thenReturn(Stream.of(strategyA, strategyB));
}
To me this is far more elegant as it doesn't require you to add a helper method that is only relevant to testing to your code.
The solution from Erwin Dupont is nice but does not work when you need to inject the List of mocks in the constructor of the tested object.
Here's how I got round that. I've shown the solution for just 1 item in the list, but you could extend it to N items by putting a switch(index)
into the get()
method:
class Wrapper {
private final List<Strategy> strategies;
Wrapper(List<Strategy> strategies) { this.strategies = new ArrayList<>(strategies); }
// ...
}
class WrapperTest {
@InjectMocks
private Wrapper testedObject;
@Spy
private List<Strategy> mockedStrategies new AbstractList<Strategy>() {
@Override public Trigger get(int index) { return trigger; } // can get away without bounds-checking
@Override public int size() { return 1; }
};
@Mock
private Strategy strategy;
@Test
public void testSomething() {
assertThat(testedObject).isNotNull();
assertThat(testedObject.getStrategies()).hasSize(1);
}
}