2016-07-30 4 views
3

У меня есть служба, которую я хочу инициализировать с помощью @PostConstuct, извлекая некоторые записи конфигурации в Config.groovy.Обслуживание нестационарных графов (2.5.4) с использованием @PostConstruct с тестированием модуля Spock

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

При написании модульного теста для этой услуги я пришел в тупик в Споке.

Спок, по-видимому, вызывает метод @PostConstruct, но только на экземпляре Shared Service, а затем выполняет любые методы экземпляра, которые вы тестируете, в реальном тестируемом экземпляре.

Это извращенный побочный эффект:

Моей инициализация код либо не удается, потому что я не добавить setupSpec инициализировать общий экземпляр, или он не в методе испытуемого, поскольку конфигурация не была фактически установлена в этом случае.

Вот моя служба:

package issue 

import org.codehaus.groovy.grails.commons.GrailsApplication 

import javax.annotation.PostConstruct 

class MyService { 
    GrailsApplication grailsApplication 
    String property 

    @PostConstruct 
    void init() { 
     println "Initializing... ${this}" 
     property = grailsApplication.config.myProperty 

//Enabling this business sanity check make the service untestable under Spock, because to be able to run, we need to initialize the configuration 
// of the shared instance - PostConstruct is only called on the shared instance for some reason. 
// But the execution of the method under test will not have the initialized property, because the service being executed is not the shared instance 
     if (property == "[:]") { 
      throw new RuntimeException("This property cannot be empty") 
     } 
    } 


    void doSomething() { 
     println "Executing... ${this}" 
     println(property.toLowerCase()) 
    } 
} 

Вот мой первый тест:

package issue 

import grails.test.mixin.TestFor 
import spock.lang.Specification 

@TestFor(MyService) 
class MyServiceSpec extends Specification { 

    def setup() { 
     grailsApplication.config.myProperty = 'myValue' 
    } 

    void "It fails to initialize the service"() { 
     expect: 
     false // this is never executed 
    } 
} 

Вот второй тест:

package issue 

import grails.test.mixin.TestFor 
import spock.lang.Specification 

@TestFor(MyService) 
class MyServiceWithSharedInstanceInitializationSpec extends Specification { 

    //Initializing the shared instance grailsApplication lets the @PostConstruct work, but will fail during method test 
    //because the instance that was initialized is the shared instance 
    def setupSpec() { 
     grailsApplication.config.myProperty = 'myValue' 
    } 

    void "It fails to execute doSomething"() { 
     when: 
     service.doSomething() 

     then: 
     def e = thrown(NullPointerException) 
     e.message == 'Cannot invoke method toLowerCase() on null object' 
     service.property == null 
    } 
} 

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

Вы можете увидеть мое полное Grails приложение здесь:

https://github.com/LuisMuniz/grails-spock-issue-with-postconstruct

ответ

2

Мой инициализации код либо не удается, потому что я не добавить setupSpec инициализировать общий экземпляр, или он не в методе тестируемый , поскольку на этом экземпляре конфигурация фактически не была установлена.

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

+0

Правда, это приемлемо. Тестирование @PostConstuct является аспектом интеграции – loteq