web-dev-qa-db-de.com

Mockito - Injizieren einer Liste von Mocks

Ich habe folgenden Code:

@Component 
public class Wrapper
{ 
    @Resource 
    private List<Strategy> strategies;

    public String getName(String id)
    {
    // the revelant part of this statement is that I would like to iterate over "strategies"
        return strategies.stream()
            .filter(strategy -> strategy.isApplicable(id))
            .findFirst().get().getAmount(id);
    } 
}

@Component 
public class StrategyA implements Strategy{...}

@Component 
public class StrategyB implements Strategy{...}

Ich möchte einen Test dafür mit Mockito erstellen. Ich habe den Test wie folgt geschrieben:

@InjectMocks
private Wrapper testedObject = new Wrapper ();

// I was hoping that this list will contain both strategies: strategyA and strategyB
@Mock
private List<Strategy> strategies;

@Mock
StrategyA strategyA;

@Mock
StrategyB strategyB;

@Test
public void shouldReturnNameForGivenId()
{   // irrevelant code...
    //when
    testedObject.getName(ID);
}

Ich erhalte die NullPointerException online:

filter(strategy -> strategy.isApplicable(id))

, die besagt, dass die "Strategien" -Liste initialisiert, aber leer ist. Gibt es eine Möglichkeit, wie Mohito sich im selben Gewand wie Spring verhält? Alle Instanzen, die die Schnittstelle "Strategie" implementieren, automatisch zur Liste hinzufügen?

Übrigens habe ich keine Setter in der Wrapper-Klasse und würde es gerne so lassen, wenn es möglich ist.

7
fascynacja

Mockito kann nicht wissen, dass Sie etwas in die Liste aufnehmen wollen Strategien .

Sie sollten dies überdenken und so etwas tun

@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);
}
0
thopaw

Kommentieren Sie es mit @Spy anstelle von @Mock. Verwenden Sie eine konkrete Implementierung, beispielsweise ArrayList, da Mockito eine Schnittstelle nicht ausspionieren kann. Fügen Sie während des Testaufbaus die Mocks zum Listenspion hinzu. Auf diese Weise müssen Sie Ihr Testobjekt nicht nur zu Testzwecken ändern.

@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);
}
8
Erwin Dupont

Sie sollten Sammlungen nicht verspotten.

Erstellen Sie die gewünschten Mocks und fügen Sie sie in eine Liste ein:

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);
}
1
Timothy Truckle

Warum verspotten Sie nicht einfach Ihren Anruf bei 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));
}

Für mich ist dies weitaus eleganter, da Sie keine Hilfsmethode hinzufügen müssen, die nur für das Testen Ihres Codes relevant ist.

0
Naruto Sempai