2014-01-16 4 views
1

источника данных Я пытаюсь написать блок прецедент для контроллера Grails, который имеет следующую структуру:Grails модульное тестирование с несколькими

class MyController{ 

    def save(){ 
     def myDomain = new MyDomain(params) 
     business validation 1 
     business validation 2 
     myDomain.writedatasource.save() 
     business validation 3 
     business validation 4 
    } 
} 

Поскольку тест блока не загружает DataSource.groovy writedatasource не доступен во время модульного тестирования, так что тестовые примеры для «бизнес проверки 3» и «бизнес-проверки 4» терпят неудачу, как я получаю

groovy.lang.MissingPropertyException: нет такого свойства: writedatasource для класса: MYDOMAIN

Как я могу изменить свой тестовый пример для проверки сценариев проверки 3 и 4?

Тестовый пример прост и выглядит следующим образом:

void testSave(){ 
    ...setup... 
    controller.save() 
    assert conditions 
    .... 

} 
+2

Интересный вопрос. Вам придется издеваться над источником данных или даже лучше, если вместо этого вы напишете тест интеграции –

+0

Согласитесь, что интеграционный тест, безусловно, выполнит эту работу, но у нас есть несколько примеров таких сценариев (почти 80% компонентов), поэтому, если мы будем писать тесты интеграции для каждый из них тогда, по существу, не будет никакого модульного тестирования. Даже если мы издеваемся над источником данных, как вы присоединяете его к myDomain, чтобы он был доступен контроллеру для создания myDomain.writedatasource.save(). –

ответ

1

Не уверен, если это может сделать трюк, но вы можете попробовать:

def 'the controller call the save method in writedatasource'() { 
    given: 
     def calls = 0 
    and: 
     def myDomainInstance = new MyDomain() 
    and: 
     MyDomain.metaClass.getWritedatasource = { new Object() } 
    and: 
     Object.metaClass.save = { Map attrs -> 
      calls++ 
     } 
    when: 
     controller.save() 
    then: 
     calls == 1 
} 

Но единственное, что вы делаете, это тестирование что сохранение вызывается под writedatasource, поэтому было бы лучше иметь также интеграционный тест. Если это делает трюк, ответьте также на http://grails.1312388.n4.nabble.com/Mocking-in-a-unit-test-a-domain-object-multiple-datasources-td4646054.html, поскольку они, похоже, имеют ту же проблему.

+0

Я только что понял, что я привел пример с помощью Спока, но я думаю, что вы можете принять его важную часть. –

+0

Спасибо, что помогли. Я пытался метакасс на строку, но новый объект работает лучше.Ниже то, что я пошел с: \t \t \t \t Object.metaClass.save = {арг -> возвращает истину} \t \t \t \t myDomain.metaClass.rmprw = новый Object() –

+0

только, чтобы избежать путаницы, это writedatasource не rmprw. Object.metaClass.save = {args -> return true} myDomain.metaClass.writedatasource = new Object() –

1

адресация оригинальный вопрос:

Я столкнулся с этим и пришлось бы издеваться много, много больше методов, чем просто «сохранить» на нескольких доменах. Так вместо этого, я отменяю сорбент из моих доменов просто возвращаю экземпляр домена ссылающегося:

def setup() { 
    [MyDomain1, MyDomain2].each { Class clazz -> 
     mockDomain(clazz) 
     clazz.metaClass.getWritedatasource = { 
      return delegate 
     } 
     clazz.metaClass.'static'.getWritedatasource = { 
      return delegate 
     } 
    } 
} 

Это также спасает меня от включения @DirtiesRuntime, так как я не обновляя метакласс все, что я хотел бы убрать.

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

Что делать, если вам нужны динамические источники данных?

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

static mapping = { 
    datasources Holders.grailsApplication?.config.dynamic?.datasources 
    ... 
} 

где dynamic.datasources представляет собой массив имен DataSource. Затем в тестовой настройке:

def setup() { 
    grailsApplication.config.dynamic.datasources = ['foo', 'bar'] 
    [MyDomain1, MyDomain2].each { Class clazz -> 
     mockDomain(clazz) 
     grailsApplication.config.dynamic.datasources.each{ 
      clazz.metaClass."get${it.capitalize()}" = { 
       return delegate 
      } 
      clazz.metaClass.'static'."get${it.capitalize()}" = { 
       return delegate 
      } 
     } 
    } 
} 
+0

Хорошее решение, хотя это не сработало бы для меня, пока я правильно не определил блок установки с аннотацией. @ Перед тем, как void setup() {...} – Peter

Смежные вопросы