Метод Stubbed должен возвращать значение в зависимости от заданного параметра mock в Spock - PullRequest
0 голосов
/ 03 июля 2018

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

class ExampleSpec extends Specification {

    def "should return second value of list of return values"() {
        given:
        Person personBob = Mock()
        Person personJackson = Mock()
        PersonHelper stubbedPerson = Stub()

        stubbedPerson.getNameOfBrother(personBob) >> "Billy Bob";
        stubbedPerson.getNameOfBrother(personJackson) >> "Tommy Jackson";

        when:
        String actual = stubbedPerson.getNameOfBrother(personBob)
        String actual2 = stubbedPerson.getNameOfBrother(personJackson)

        then:
        actual == "Billy Bob" // true
        actual2 == "Tommy Jackson" // false "Billy Bob"
    }

}

Тест не пройден, поскольку второй вызов для var actual2 по-прежнему возвращает Билли Боб , а не Томми Джексон . Я знаю, что есть способ вернуть разные значения по порядку вызовов, но я бы хотел, чтобы он зависел от заданных макетов.

Использование нормальных значений - без Mock / Stub Proxy - поскольку значения параметров действительно работают. Я предполагаю, что двигатель Спока не может отличаться между двумя макетами. Но я не уверен в этом, потому что прокси имеют идентификаторы в качестве полей экземпляра.

1 Ответ

0 голосов
/ 03 июля 2018

Для справки - заглушка с фиктивными объектами работает. Я добавил простые Person и PersonHelper классы к вашему примеру, и тест прошел:

import spock.lang.Specification

class ExampleSpec extends Specification {

    def "should return second value of list of return values"() {
        given:
        Person personBob = Mock()
        Person personJackson = Mock()
        PersonHelper stubbedPerson = Stub()

        stubbedPerson.getNameOfBrother(personBob) >> "Billy Bob";
        stubbedPerson.getNameOfBrother(personJackson) >> "Tommy Jackson";

        when:
        String actual = stubbedPerson.getNameOfBrother(personBob)
        String actual2 = stubbedPerson.getNameOfBrother(personJackson)

        then:
        actual == "Billy Bob" // true
        actual2 == "Tommy Jackson" // false "Billy Bob"
    }

    static class Person {
        String name
    }

    static class PersonHelper {
        String getNameOfBrother(Person person) {
            return null
        }
    }
}

Я проверил это с spock-core:1.1-groovy-2.4, spock-core:1.0-groovy-2.4 и даже spock-core:0.7-groovy-2.0. Все сработало.

Но что еще важнее - такой тест не имеет никакого смысла . Вы не проверяете свой код вообще. Вы только проверяете, корректно ли дразнит рамки. Этот тест может иметь некоторый смысл, если вы используете макеты Спока в своем производственном коде, но это неверное предположение.

Что может пойти не так?

Подумайте секунду об этом тесте. В соответствии с вашим блоком when: вы пытаетесь проверить, возвращает ли PersonHelper.getNameOfBrother(Person person) действительное имя брата для двух разных объектов. Теперь давайте предположим, что это единственный тест класса PersonHelper в вашем проекте. Представьте, что произойдет, если вдруг реализация метода getNameOfBrother начнет выбрасывать NullPointerException по некоторой случайной причине. Спросите себя - защищает ли вас юнит тест от такой ситуации? Нету. Ваш тест всегда проходит, потому что вы заглушаете метод, который вы тестируете. Если вместо этого вы тестируете реальную реализацию и передаете реальный объект Person, вы получите уведомление о NullPointerException в тесте. В противном случае вы увидите это, когда развернете свой код, и некоторые действия пользователя вызовут этот метод, и он завершится неудачей.

...