gpt4 book ai didi

unit-testing - 使用@PostConstruct 和 Spock 单元测试的不可测试的 grails (2.5.4) 服务

转载 作者:行者123 更新时间:2023-12-04 04:55:01 25 4
gpt4 key购买 nike

我有一个服务,我想用 @PostConstuct 初始化,方法是在 Config.groovy 中获取一些配置条目。

我还希望检查这些条目是否已正确配置,并抛出异常以便我看到应用程序配置错误。

在为这项服务编写单元测试时,我在 Spock 中走入了死胡同。

Spock 显然调用了 @PostConstruct 方法,但仅在共享服务实例上,然后在被测真实实例上执行您测试的任何实例方法。

这有一个反常的副作用:

我的初始化代码失败是因为我未能添加 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

最佳答案

My init code either fails because I fail to add a setupSpec to initialize the shared instance, or it fails in the method under test, because the configuration has not actually been set on that instance.

我的建议是简单地调用 init 方法,因为您正在测试该方法的逻辑和功能,而不是 @PostConstruct 是否有效,这似乎最有意义。

关于unit-testing - 使用@PostConstruct 和 Spock 单元测试的不可测试的 grails (2.5.4) 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38676078/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com