2017-02-20 5 views
4

У меня есть следующий код:Mockito - Инъекция списка издевается

@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{...} 

Я хотел бы создать тест для его использования Mockito. я написал тест следующим образом:

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

Я получаю NullPointerException на линии:

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

, в котором говорится, что список «стратегии» инициализируется, но пуста. Есть ли способ, которым Мохито будет вести себя так же, как Весна? Автоматическое добавление всех экземпляров, реализующих интерфейс «Стратегия» к списку?

Btw У меня нет никаких сеттеров в классе Wrapper, и я хотел бы оставить его таким образом, если это возможно.

ответ

1

Mockito не может знать, что вы хотите поставить Somthing в список стратегий.

Вы должны пересмотреть ли это сделать что-то вроде этого

@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

Томас, весна как-то знает .. Так что мне было интересно, если Mockito может последовать та же идея. Кроме того, я не хочу добавлять установщик setStrategies в класс Wrapper. – fascynacja

+0

Весна знает либо путем сообщения (контекст приложения), либо по соглашению (например, Типы). Но я уверен, что Spring также не может подключить общие списки. Информация типа также недоступна во время выполнения, поскольку компилятор не записывает ее в байт-код из-за фазы стирания стирания. Так что я думаю, что невозможно создать издевательский список, содержащий mocks без указания/программирования. –

+0

Весна может подключить пример класса «Wrapper», введя стратегию A и бит стратегии. Контекст приложения строится только на основе аннотаций, поэтому я надеялся, что Мокито сможет сделать то же самое. – fascynacja

2

Вы не должны издеваться над коллекциями.

Создание издевается вам нужно, и поместить их в список:

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

Тимоти, я надеялся получить решение, в котором у меня нет, чтобы установить «стратегии» список явно к «testedObject» – fascynacja

0

Почему не просто издеваются свой призыв к 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)); 
} 

Для меня это гораздо более элегантно, как это не требует, чтобы добавить вспомогательный метод, который имеет отношение только к тестированию в код.

2

Аннотировать его @Spy вместо @Mock. Поскольку Mockito не может отслеживать интерфейс, используйте конкретную реализацию, например ArrayList. Во время тестовой настройки добавьте в список шпионов. Таким образом, вам не нужно изменять ваш испытуемый только в целях тестирования.

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

Спасибо человеку, объяснение конкретного имплантата было именно частью головоломки, которую я все еще отсутствовал ... Я пробовал @Mock с вызовом реальных методов ответа, но потом они не добавлены! –

Смежные вопросы