Получение исключения из «хорошего макета» EasyMock с подключенным отладчиком

#java #mocking #easymock

#java #издевательство #easymock

Вопрос:

(Отказ от ответственности — EasyMock newb)

Согласно документации (и этому сообщению), если бы я хотел использовать EasyMock для генерации объектов-заглушек, я должен использовать EasyMock.createNiceMock() . «Хороший макет» на самом деле является заглушкой, то есть объектом, который не участвует в проверке, просто возвращает значения.

Однако следующий фрагмент не удается выполнить для меня с IllegalStateException("missing behavior definition for the preceding method") , во второй foo.translate() строке.

 Foo foo = EasyMock.createNiceMock(Foo.class);
EasyMock.replay(foo); // added this line
foo.translate("a", "b");
foo.translate("a", "b"); // only the second calls throws an exception
  

Кто-нибудь может объяснить это, или, скорее, сказать мне, как использовать EasyMock для создания заглушек с нулевой детализацией (o(number_of_exercised_mock_methods)).

Редактировать — Я заметил, что я получаю эти ошибки почти всегда, когда отладчик подключен, но никогда, когда он не подключен. Есть идеи, как это может быть связано?

Ответ №1:

Дополняю ответ Джеффа.

Из метода EasyMock createNiceMock javadoc:

Создает макет объекта, который реализует данный интерфейс, проверка порядка по умолчанию отключена, и макет объекта будет возвращать 0 значение null или false для неожиданных вызовов.

Макет объекта, созданный этим методом, не нуждается в какой-либо конфигурации (ожидаемые вызовы). Вам просто нужно создать его и «воспроизвести». Пример:

 ComplicatedObject stub = EasyMock.createNiceMock();
replay(stub);
  

Любой вызов метода разрешен для созданной заглушки (он не вызовет исключения), и они всегда будут возвращать значение по умолчанию (0, null или false). Если вы настроили конкретное ожидаемое значение вызова, вам придется настроить его возвращаемое значение, иначе вы получите сообщение об ошибке (это ваш случай).

Если вы хотите ограничить, какие методы могут выполняться (что приводит к сбою теста при вызове неожиданного метода), боюсь, вам придется создать обычный макет, настроить ожидание каждого вызова и возвращаемое значение для каждого из них.

Ответ №2:

Если ваш метод translate возвращает значение, вам нужно настроить ожидаемое значение для него.

 expect(foo.translate("a","b")).andStubReturn(retVal);
  

Комментарии:

1. Разве хороший макет не должен позволять мне не устанавливать ожидания? Это означает, что если используются k методов, мне нужно настроить k ожиданий … и в этом случае меня вообще не интересуют ожидания, я просто хочу возразить против работы.

2. Я считаю, что это касается только проверки макета, а не настройки. Вы пытались добавить возвращаемое значение и посмотреть, работает ли оно? Кроме того, если вас не волнует ожидание и вам просто нужен фиктивный объект, зачем вообще беспокоиться о настройке ожидания, просто создайте приятный макет и переведите его в режим воспроизведения.

3. «добавление возвращаемого значения …» — это потребовало бы установки ожидаемых значений для всех методов, чего я пытаюсь избежать. Я вообще не хочу настраивать ожидания. Я полагаю, что приведенный выше вызов завершается неудачей, даже если я вызываю replay () после первой строки (я попробую это в следующий раз, когда буду на работе).

4. О, я что-то пропустил в вашем коде. На самом деле вы не создавали хороший макет, вы создали стандартный макет с помощью EasyMock.createMock. Используйте EasyMock.createNiceMock для создания хорошего макета.

5. Да, я подтвердил, что вам нужно добавить andStubReturn (или andReturn). Если вы хотите, чтобы метод возвращал значения по умолчанию (т. Е. false, 0 и т.д.), Просто вообще не устанавливайте никаких ожиданий, поэтому что-то вроде: Foo foo = createNiceMock(Foo.class ); replay(foo); В противном случае вам нужно добавить возвращаемое значение для методов, которые их возвращают.

Ответ №3:

Вам нужно вызвать EasyMock.replay(foo) . Прежде чем вы это сделаете, ваш макет объекта находится в «состоянии записи». Из документации EasyMock:

В состоянии записи (перед вызовом replay) макет объекта не ведет себя как макет объекта, но он записывает вызовы методов. После вызова replay он ведет себя как макет объекта, проверяя, действительно ли выполняются ожидаемые вызовы метода.

Если вы хотите создать заглушку-объект, просто вызовите, createNiceMock за replay которым следует:

 Foo foo = EasyMock.createNiceMock(Foo.class);
EasyMock.replay(foo);
foo.translate("a", "b");
foo.translate("a", "b");