Применение ограничений аргументов с помощью тестов Спока - PullRequest
1 голос
/ 07 ноября 2019

У меня есть несколько классов Java, для которых я написал тесты Спока. Когда я пытаюсь проверить точный объект, использованный в аргументе, проверка не проходит.

    def "all events are published to subscribers"() {
        given:
        EventSubscriber subscriber = Mock()
        when:
        subscriber.shouldRegister() >> true
        subscriber.interests() >> new HashSet<Intent>(Arrays.asList(COUNTER, GAUGE))
        publisher.subscribe(subscriber)
        def event = publisher.newEvent("test", COUNTER)
        event.start()
        def child = event.newChild("child", GAUGE)
        event.finish()
        then:
//        2 * subscriber.onCreate(event)
//        1 * subscriber.onStart(event, event.start)
//        1 * subscriber.onEnd(event, event.end)
//        1 * subscriber.onChild(event, child)
        2 * subscriber.onCreate(_)
        1 * subscriber.onStart(_, _)
        1 * subscriber.onEnd(_, _)
        1 * subscriber.onChild(_, _)
    }

Скомментированные строки завершаются с

groovy.lang.MissingPropertyException: Нет такого свойства: событие для класса: io.hypi.faf.api.EventPublisherTest

at io.hypi.faf.api.EventPublisherTest.all события публикуются для подписчиков (EventPublisherTest.groovy: 28)

http://spockframework.org/spock/docs/1.3/all_in_one.html#_argument_constraints, кажется, предполагает, что я могу просто передатьvalue in. Первый пример - строка, но я предполагаю, что тип не имеет значения.

Что я сделал с этим не так?

Спок: 1.3 Groovy: 2.5 groovy-test-junit5-2.5.7 JDK: 11

1 Ответ

1 голос
/ 07 ноября 2019

Экземпляры объектов, используемые в тестировании взаимодействия, должны быть определены в разделе given.

Это будет работать:

def "all events are published to subscribers"() {
    given:
    EventSubscriber subscriber = Mock()
    subscriber.shouldRegister() >> true
    subscriber.interests() >> new HashSet<Intent>(Arrays.asList(COUNTER, GAUGE))
    publisher.subscribe(subscriber)
    def event = publisher.newEvent("test", COUNTER)
    def child = event.newChild("child", GAUGE)

    when:
    event.start()
    event.finish()

    then:
    2 * subscriber.onCreate(event)
    1 * subscriber.onStart(event, event.start)
    1 * subscriber.onEnd(event, event.end)
    1 * subscriber.onChild(event, child)
}

Но тогда возникнет проблема с тестированиемвызов onCreate() и onChild(), потому что тогда эти вызовы не находятся в разделе when и могут совпадать только onStart() и onEnd().

У меня нет определений ваших классов, чтобы увидеть детали, но я предполагаю, что поля event.start и event.end инициализируются в start() и finish() методах, а затем 1 * onStart(event, event.start) и 1 * onEnd(event, event.end) testне будет соответствовать, потому что проверка вызова будет выполнена в фазе, когда event имеет различные значения start и end. Так что тогда будут соответствовать только тесты 1 * onStart(event, _) и 1 * onEnd(event, _).


Посмотрите на этот простой пример, который работает и похож на ваш случай, но с той разницей, что экземпляр event подготовлен враздел given и не изменяется в when, поэтому он пройдет тест:

class InvocationWithArgumentsSpec extends Specification {
    void 'Invocation test works with arguments other then String'() {
        given:
        def subscriber = Mock(Subscriber)
        def simplePublisher = new Publisher()
        simplePublisher.subscribe(subscriber)
        def event = new SimpleEvent(name: "test")

        when:
        simplePublisher.fireEvent(event)

        then:
        1 * subscriber.onEvent(event)
    }
}

interface Subscriber {
    void onEvent(SimpleEvent event)
}

class Publisher {
    Subscriber subscriber

    void subscribe(Subscriber subscriber) {
        this.subscriber = subscriber
    }

    void fireEvent(SimpleEvent event) {
        subscriber.onEvent(event)
    }
}

class SimpleEvent {
    String name
}

Обновление: Но есть обходной путь для вас. Это не очень хорошо, но это работает и проверяет, что правильные события передаются в методы подписчика (я думаю, что event имеет что-то вроде name):

def "all events are published to subscribers"() {
    given:
    EventSubscriber subscriber = Mock()
    subscriber.shouldRegister() >> true
    subscriber.interests() >> new HashSet<Intent>(Arrays.asList(COUNTER, GAUGE))
    publisher.subscribe(subscriber)

    when:
    def event = publisher.newEvent('test', COUNTER)
    event.start()
    event.newChild('child', GAUGE)
    event.finish()

    then:
    1 * subscriber.onCreate({ e -> e.name == 'test' })
    1 * subscriber.onCreate({ e -> e.name == 'child' })
    1 * subscriber.onStart({ e -> e.name == 'test' }, { start -> start != null })
    1 * subscriber.onEnd({ e -> e.name == 'test' }, { end -> end != null })
    1 * subscriber.onChild({ e -> e.name == 'test' }, { c -> c.name == 'child' })
}
...