Мокинг ListState в Apache Flink 1.4 - PullRequest
0 голосов
/ 18 июня 2020

Я пишу тестовый код для функции processElement в Apache Flink 1.4:

public class ProcessFunctionClass {

    public void processElement(Tuple2<String, String> tuple2,  Context context, Collector<Tuple2<String, String>> collector) {

        // if the state is empty, start a timer
        if (listState.get().iterator().hasNext() == false)
            context.timerService().registerEventTimeTimer(1000);

        listState.add("someStringToBeStored");

        // ...
    }

}
public class ProcessFunctionClassTest {

    private ProcessFunctionClass processFunctionClass;

    @Mock
    private ListState<String> listState;

    @Before
    public void setUp() throws Exception {
        processFunctionClass = new ProcessFunctionClass();
    }

    @Test
    public void testProcessElement() {

        ListState mockListState = mock(ListState.class);
        Iterable mockIterable = mock(Iterable.class);
        Iterator mockIterator = mock(Iterator.class);
        MockitoAnnotations.initMocks(this);

        when(tDPListState.get()).thenReturn(mockIterable);
        when(tDPListState.get().iterator()).thenReturn(mockIterator);
        when(tDPListState.get().iterator().hasNext()).thenReturn(false);

        processFunctionClass.processElement(tuple2, context, collector);

        // verify(...)
    }
}

Когда я отлаживаю с помощью своей IDE, непосредственно перед тем, как войти в processElement() Метод listState не null и, похоже, был успешно издеваться, но как только я добираюсь до listState.get().iterator().hasNext(), listState становится null, и я получаю исключение NullPointerException. Что я здесь делаю не так?

1 Ответ

1 голос
/ 18 июня 2020

В ProcessFunctionClass у вас есть частная переменная listState. В своем тесте вы создаете совершенно несвязанную переменную mockListState и устанавливаете для нее некоторые ожидания.

Чтобы ваш тест работал, вы должны предоставить способ (конструктор или установщик) для установки ProcessFunctionClass.listState на желаемое значение ( состояние вашего фиктивного списка)

Вдобавок к этому MockitoAnnotations.initMocks(this);, похоже, ничего не делает в вашем примере: вы не показали нам никаких полей, помеченных @Mock или @InjectMocks

Обновить

Вы неправильно используете аннотацию @Mock. Вы должны поместить его в тестовый класс, а не в тестируемый класс. При размещении в тестовом классе после вызова initMocks поле будет инициализировано имитацией соответствующего типа.

Что вам следует вместо этого:

  • remove MockitoAnnotations.initMocks(this);, вы создаете все макеты вручную.
  • добавьте конструктор в ProcessFunctionClass
public ProcessFunctionClass(ListState<String> listState) {
    this.listState = listState
}
  • используйте этот конструктор в своем тесте
var mockListState = mock(ListState.class);
var processFunctionClass = new ProcessFunctionClass();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...