Тест на основе взаимодействия Спока: слишком мало вызовов метода - PullRequest
0 голосов
/ 24 июня 2018

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

Ниже приведен тест, который просто проверяет, что оба метода были вызваны правильно. Но все равно получаю 0 ошибка вызова на обоих методах. Что вызывает эту проблему?

AuthApiKeyPair updateApiKeyPair(AuthApiKeyPair apiKeyPair, Boolean createNewKey) {

    AuthApiKeyPair newKeyPair

    if (createNewKey) {
        deleteApiKeyPair(apiKeyPair)

        //The key will be created with the same info as the previous key.
        newKeyPair = createApiKeyPair(apiKeyPair.label, apiKeyPair.accountMode, apiKeyPair.source)
    }

    newKeyPair
}

TEST:

def "should soft delete key pair and create new one"() {
    setup:
    AuthApiKeyPair apiKeyPair = AuthApiKeyPair.build(acquirerId: 123, source: PaymentSource.BOARDING_API, label: 'Boarding API key')

    when:
    service.updateApiKeyPair(apiKeyPair, true)

    then:
    1 * service.deleteApiKeyPair(apiKeyPair)
    1 * service.createApiKeyPair(apiKeyPair.label, apiKeyPair.accountMode, apiKeyPair.source)
}

1 Ответ

0 голосов
/ 24 июня 2018

Если вы подумаете о своем тесте, вы поймете, что в лучшем случае он проверяет механизм спока, а не ваш бизнес-код. Вы не показали нам полный класс со своей спецификацией теста, однако, исходя из вашего сценария, мы можем предположить, что service в вашем тесте - просто фальшивка. Если это правда, то вы не можете ожидать этих двух вызовов:

then:
1 * service.deleteApiKeyPair(apiKeyPair)
1 * service.createApiKeyPair(apiKeyPair.label, apiKeyPair.accountMode, apiKeyPair.source)

случиться. Просто потому, что смоделированный класс не выполняет реальные методы.

Я бы настоятельно рекомендовал вам протестировать реальный класс, а не то, какие вызовы вызывает конкретный метод, а каковы ожидаемые (и детерминированные) результаты вызова конкретного метода (ов) . Вы можете выполнить service.updateApiKeyPair(apiKeyPair, true) для реального объекта в предложении when, а затем проверить, была ли создана новая пара ключей API (и сохранена ли она в используемом вами хранилище) и не существует ли старая пара больше. Такой тест имеет по крайней мере несколько преимуществ по сравнению только с проверкой вызовов:

  • вы можете изменить реализацию service.updateApiKeyPair() в любое время и до тех пор, пока она дает те же результаты, ваш тест по-прежнему полезен (поскольку тест не ограничивает вашу реализацию, как это делает тест вызова),
  • вы тестируете реальное поведение, а не издеваетесь над библиотекой - есть такая В анекдоте говорится, что Mockito - самая проверенная библиотека за всю историю миллионов проектов.

Конечно, это может потребовать некоторых изменений дизайна. Я предполагаю, что в вашем классе обслуживания используется какой-то внедренный DAO или репозиторий, в котором хранятся пары ключей API. Подумайте о предоставлении реализации DAO в памяти для вашего теста - класса, который вместо сохранения объектов в реальной базе данных хранит все объекты во внутренней ConcurrentMap<K,V>. Благодаря этому вы все равно можете запустить свой тест как модульный тест и проверить, выполняет ли обновление пары ключей API с параметром createNewKey, установленным на true, именно то, что вы ожидаете. В качестве альтернативы вы могли бы написать интеграционный тест с заменой базы данных H2, но это только увеличит длительность начальной загрузки теста. Выбор за вами.

Есть одно правило, которое стоит запомнить - если ваш класс / компонент / функциональность и т. Д. Сложно тестировать модулем, это означает, что был сделан неправильный выбор дизайна.

Альтернатива: объекты Спока Spy

Есть одна вещь, которую я упоминаю в конце специально. Спок поддерживает так называемые «шпионские» объекты, которые ведут себя как реальные объекты, но они позволяют вам заглушить некоторые части и обрабатывать этот объект как издевательство, например. подсчет вызовов. Но даже авторы Spock предупреждают разработчиков об использовании этой функции:

(Подумайте дважды, прежде чем использовать эту функцию. Возможно, лучше изменить дизайн кода в соответствии со спецификацией.)

Источник: http://spockframework.org/spock/docs/1.0/interaction_based_testing.html#spies

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

...