Проверка завершается с ошибкой, если значение для элемента eq () предоставляется путем вызова метода mocked [duplicate]

Это затронет только небольшую часть пользователей, но я бы хотел, чтобы это было документировано для этой небольшой части. Из-за этой проблемы этот член этой маленькой горстки потратил 6 часов на устранение неполадок с работающим PHP-почтовым скриптом.

Если вы собираетесь в университет, в котором работает XAMPP с сайта www.AceITLab.com, вы должны знать, что наш профессор не сказал нам: брандмауэр AceITLab (а не брандмауэр Windows) блокирует MercuryMail в XAMPP , Вам придется использовать альтернативный почтовый клиент, груша работает на нас. Вам нужно будет отправить учетную запись Gmail с низкими настройками безопасности.

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

2
задан Tama Yoshi 29 April 2016 в 19:11
поделиться

2 ответа

Как уже упоминалось в моем комментарии, Мокито на самом деле несовместим с интуицией; много раз метод, который был заглушен или проверен, является просто «последним вызываемым методом», главным образом потому, что синтаксис, подобный verify(foo).doA(), фактически вызывает doA, а не передачу рефлексивной ссылки на метод doA в Mockito. Это просто несовместимо с синтаксисом, который вызывает тот же макет в середине stubbing или проверки.

Я написал об этом раньше в отношении Matchers , которые имеют такая же проблема во время stubbing. Выпивая исходный код, вы можете увидеть ту же проблему с проверкой, по крайней мере, при вызове метода в том же макете.

Короче говоря, проверка на самом деле является трехфазным процессом:

  1. Вызов verify(mockedThing).
  2. Соединители вызовов, при необходимости, при необходимости. Не вызывайте какие-либо методы на mockedThing.
  3. Вызовите метод, который вы проверяете на mockedThing, с фактическими значениями параметров, если вы не используете совпадения, а также фиктивные (игнорируемые) значения параметров, если вы используете матчи. Поскольку Mockito отслеживает стек меток в фоновом режиме, методы сопоставления могут возвращать 0 или null без Mockito, считая, что это значения для проверки.

Под обложками

Вызывает verify фактически просто устанавливает флаг и возвращает тот же макет :

public <T> T verify(T mock, VerificationMode mode) {
  // [catch errors]
  mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, mode));
  return mock;
}

Затем внутри обработчика, который обрабатывает все макетные вызовы , Mockito начинает проверку при первом вызове макета, который происходит после начала проверки:

public Object handle(Invocation invocation) throws Throwable {
  // [detect doAnswer stubbing]
  VerificationMode verificationMode = mockingProgress.pullVerificationMode();
  // [check Matcher state]

  // if verificationMode is not null then someone is doing verify()
  if (verificationMode != null) {
    // We need to check if verification was started on the correct mock
    // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)
    if (((MockAwareVerificationMode) verificationMode).getMock() == invocation.getMock()) {
      VerificationDataImpl data = createVerificationData(invocationContainerImpl, invocationMatcher);
      verificationMode.verify(data);
      return null;
    } else {
      // this means there is an invocation on a different mock. Re-adding verification mode
      // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)
      mockingProgress.verificationStarted(verificationMode);
    }
  }

  // [prepare invocation for stubbing]
}

Поэтому, если вы взаимодействуете с макетом только с получить значение параметра, Mockito собирается предположить, что вы на самом деле вызываете метод для проверки. Обратите внимание, что если вызов был немного другим, например verify(mockedThing).doB(eq(5), eq(mockedThing.doA())); с дополнительным eq(5), вы получили бы другое сообщение об ошибке при использовании маркеров - особенно потому, что Mockito не просто думает, что вы проверяете doA, но это вы как-то думаете, что doA принимает аргумент.

Последствия

Ваш код не работает:

// DOESN'T WORK
verify(mockedThing).doB(eq(mockedThing.doA()));
// BECAUSE IT BEHAVES THE SAME AS
verify(mockedThing).doA();

Но извлечение его действительно работает:

// WORKS, though it makes an extra call to doA
Value value = mockedThing.doA();
verify(mockedThing).doB(eq(value));

И это также работает и показывает, что происходит под обложками, но никогда не пишите это в реальном тесте:

// WORKS BUT DON'T EVER ACTUALLY DO THIS
Value value = mockedThing.doA();
verify(mockedThing);
eq(value);
mockedThing.doB(8675309 /* dummy value ignored because of matcher */);
4
ответ дан Jeff Bowman 22 August 2018 в 03:09
поделиться

Ответ Джеффа Боумана помогает объяснить, что происходит.

Многие из Mockito основаны на последней вызываемой функции и называет mocks неявно проверять состояние способами, которые не совместимы с синтаксисом, который вы пытаетесь использовать. Я написал немного больше об этом ответе здесь. - вчера Джефф Боумен

1
ответ дан Community 22 August 2018 в 03:09
поделиться
  • 1
    Рад, что это помогло! Извините, у меня не было времени, чтобы опубликовать подробный ответ (я был на своем телефоне); Я добавил один с более подробной информацией, если вам интересно. Ура! – Jeff Bowman 1 May 2016 в 17:43
Другие вопросы по тегам:

Похожие вопросы: