JMockit: смоделированная коллекция bean-компонентов не работает с Stream API - PullRequest
1 голос
/ 01 октября 2019

У меня есть простой метод, который нужно протестировать с помощью JMockit, но кажется, что использование Stream API требует дополнительной проверки, но я не понимаю, что именно я должен добавить.

Метод, который работает с использованием for-loop

private final List<ValueProcessor> valueProcessors;

public List<Response> proc(Entry value) {
    List<Response> badResponses = new ArrayList<>();
    for (ValueProcessor processor : valueProcessors) {
        List<Response> responses = processor.process(value);
        if (!CollectionUtils.isEmpty(responses)) {
                badResponses.addAll(responses);
        }
    }
    return badResponses;
}

Тот же код с использованием Stream API:

public List<Response> proc(Entry value) {
    return valueProcessors.stream()
            .map(processor -> processor.process(value))
            .filter(collection -> !CollectionUtils.isEmpty(collection))
            .flatMap(Collection::stream)           
            .collect(Collectors.toList());
}

Я хочу проверить код, используя JMockit, поэтому у меня есть следующий тест

@RunWith(JMockit.class)
public class ProcessorTest {
    @Injectable
    private List<ValueProcessor> valueProcessors = Collections.singletonList(processor -> Collections.singletonList(new Response()));
    @Tested
    private Processor processor;

    @Test
    public void testProc() {
        assertThat(processor.proc(null)).hasSize(1);
    }
}

Тест всегда проходит для метода с for-loop и всегда не проходит для метода с Stream. Как я могу это исправить?

Спасибо!

1 Ответ

1 голос
/ 02 октября 2019

Насколько я понимаю, когда вы создаете список valueProcessors, используя @Injectable, вы создаете макет списка.

Это означает, что методы из указанного списка будут посмеиватьсятак что они будут возвращать «пустые» значения по умолчанию (если через блоки Expectation ничего не указано).

Таким образом, в первом непотоковом коде, так как в списке не вызывается никаких методов, нет проблем

Но во втором коде, использующем поток, вызов valueProcessors.stream() выполняет «пустое» смоделированное поведение, которое возвращает пустой поток, и поэтому все остальное тоже становится пустым.

Решение, с которым я столкнулся, заключается в создании тестируемого экземпляра, передавая ему «реальный» список вместо поддельного:

@RunWith(JMockit.class)
public class StackOverflowTest {

    // empty injectable just so that the processor can be created
    @Injectable
    private List<ValueProcessor> valueProcessors;

    // availableDuringSetup = true to be able to modify the processor
    @Tested(availableDuringSetup = true)
    private Processor processor;

    @Before
    public void setUp() throws Exception {
        // create new instance of the processor (now the valueProcessors list is a real list)
        processor = new Processor(Collections.singletonList(processor -> Collections.singletonList(new Response())));
    }

    @Test
    public void testProc() {
        assertThat(processor.proc(null), hasSize(1));
    }

}
...