如何在单元测试中绑定@Value 注释的服务字段?

How to bind @Value annotated fields of service in unit tests?

服务:

@GrailsCompileStatic
class MyService {
    final static String PLACEHOLDER = '<x>'

    @Value('${myService.url}')  // Suppose it http://example.com/doc-<x>.html 
    private String urlTemplate

    String getSomeUrl(String lang) {
        urlTemplate.replace(PLACEHOLDER, lang)
    }
}

单元测试:

@TestFor(MyService)
class MyServiceSpec extends Specification {

    @Unroll
    void "test get some url for #lang"() {
        when:
            def someUrl = service.getSomeUrl(lang) // NullPointerException, because urlTemplate is null
        then:
            someUrl.endsWith(lang + '.html')
        where:
            lang << ['es', 'en']
    }
}

因此,正如我上面提到的,urlTemplate 为空(但配置值存在于 .properties 中)。如何解决?


解决方案:

class MyServiceSpec extends IntegrationSpec {

    MyService myService

    @Unroll
    void "test get some url for #lang"() {
        when:
            def someUrl = myService.getSomeUrl(lang)
        then:
            someUrl.endsWith(lang + '.html')
        where:
            lang << ['es', 'en']
    }
}

单元测试用于测试孤立的代码单元。如果您正在测试依赖于配置值的行为,请将其注入单元测试以实现可重用的单元测试。

另一方面,如果您要测试变量是否实际设置或变量设置为什么,则需要使用集成测试,因为您基本上是在测试与 Grails 配置机制的集成:http://docs.grails.org/latest/guide/testing.html#integrationTesting

作为第三种选择,您还可以使用功能测试来验证最终一切似乎都按预期运行:http://docs.grails.org/latest/guide/testing.html#functionalTesting

How to bind @Value annotated fields of service in unit tests?

一种方法...

@TestFor(MyService)
class MyServiceSpec extends Specification {

    @Unroll
    void "test get some url for #lang"() {
        when:
        service.urlTemplate = 'some value'
        def someUrl = service.getSomeUrl(lang)

        then:
        someUrl.endsWith(lang + '.html')

        where:
        lang << ['es', 'en']
    }
}

如果这对某人有帮助。

我遇到一个问题,@Value 中使用的缺失 属性 变量给我一个服务单元测试的 BeanExpressionException。我发现在我的 application.yml 中为测试环境设置该变量解决了我在 Grails 4 中的问题。

@有问题的值:

@Value("#{${some_property_here}}") public Map<String, Map<String, Integer>> SOME_MAP_OF_MAPS