Динамические методы Grails отсутствуют при выполнении интеграционных тестов

Я работаю над проектом с использованием Grails 2.5.4 и в настоящее время пытаюсь запустить некоторые интеграционные тесты, которые не выполняются. Я отладил проблему и обнаружил, что, по-видимому, некоторые динамические методы в тестируемых сервисах отсутствуют при запуске интеграционного теста (если вы запускаете его в контексте приложения, методы есть, и все работает). Это происходит во многих тестах, которые я пытаюсь запустить, я выбрал один в качестве примера, но у других, которые терпят неудачу, есть те же проблемы.

У меня есть этот класс домена

class Event {
...
    static hasMany = [
        bundles : Bundle
    ]
...    
}

и метод обслуживания для тестирования:

@Transactional
class BundleService {
...
    void assignEvent(Event event, List bundleIds) {
    ..
        for (id in bundleIds) {
            event.addToBundles(Bundle.get(id))
        }
    }
...
}

Итак, я запускаю этот тест спока

class BundleServiceIntegrationSpec extends Specification {

    BundleService bundleService
    EventService  eventService
    private BundleTestHelper bundleHelper = new BundleTestHelper()

    ...

    void '04. Test deleteBundleAndAssets method'() {
    when: 'a new Bundle is created'
        Bundle bundle = bundleHelper.createBundle(project, 'Test Bundle')
    and: 'a new Event is created'
        Event event = eventService.create(project, 'Test Event')
    and: 'the above Bundle is assigned to the Event'
        bundleService.assignEvent(event, [bundle.id])
    ...
}

происходит сбой в строке moveEvent.addToBundles(Bundle.get(id)) BundleService со следующим исключением

groovy.lang.MissingMethodException: No signature of method: 
net.domain.Event.addToBundles() is applicable for argument 
types: (net.domain.Bundle) values: [Test Bundle]
Possible solutions: getBundles()
at net.service.BundleService.$tt__assignEvent(BundleService.groovy:101)

Проблема заключается в том, что метод addToBundles(), который Grails должен динамически добавлять в класс Event из-за набора "bundles" коллекции hasMany, не добавляется. Как я уже говорил, если вы запускаете приложение и используете этот сервис, метод есть, и все работает.

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

Есть ли причина, по которой этот метод, который должен присутствовать в сервисе, отсутствует в контексте интеграционных тестов? Спасибо

2 ответа

@Szymon Stepniak Спасибо за ваш ответ и извините за поздний ответ. Я проверил то, что вы предложили, но это не сработало. Позже я прочитал, что grails.test.mixin.Mock аннотация предназначена только для модульных тестов и не должна использоваться в интеграционных тестах. Это также верно для @TestFor а также @TestMixin аннотации (я читал об этом в этом посте).
Поэтому после этого коллега на работе предложил мне поискать аннотации такого рода в других тестах, полагая, что это может привести к некоторому загрязнению теста между тестами и после удаления @TestFor аннотация в одном из тестов, которые ранее выполнялись как часть всего комплекта интеграционных тестов, провалившийся тест, который я опубликовал, начал работать. Самая странная вещь (приложение от компилятора не жалуется на это) - это тест на оскорбления (тот, с которого я удалил @TestFor аннотация) проходила все зеленое, это даже не подвело!
Поэтому, если у кого-то есть подобная проблема, я предлагаю поискать подобные аннотации модульных тестов в любом месте всего комплекта интеграционных тестов и удалить их, потому что компилятор не будет жаловаться, но по моему опыту это может повлиять на другие тесты и может привести к очень странному поведению.

Вам не хватает grails.test.mixin.Mock аннотации в вашем тестовом классе. В модульном тесте Grails этот миксин используется для генерации всех связанных с доменом методов для класса, чтобы вы могли правильно использовать этот домен в модульном тесте. Нечто подобное должно сработать:

@Mock([Event])
class BundleServiceIntegrationSpec extends Specification {

    BundleService bundleService
    EventService  eventService
    private BundleTestHelper bundleHelper = new BundleTestHelper()

    ...

    void '04. Test deleteBundleAndAssets method'() {
    when: 'a new Bundle is created'
        Bundle bundle = bundleHelper.createBundle(project, 'Test Bundle')
    and: 'a new Event is created'
        Event event = eventService.create(project, 'Test Event')
    and: 'the above Bundle is assigned to the Event'
        bundleService.assignEvent(event, [bundle.id])
    ...
}

Подробнее о тестировании классов доменов можно узнать здесь: https://grails.github.io/grails2-doc/2.4.5/guide/testing.html

Другие вопросы по тегам