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

Service:

@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)
    }
}

Unit test:

@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']
    }
}

So, as I mentioned above, urlTemplate is null (but config value exists in .properties). How to fix it?


Solution:

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']
    }
}


Solution 1:[1]

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

One way to do it...

@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']
    }
}

Solution 2:[2]

In case this helps someone.

I had an issue where a missing property variable used in a @Value was giving me an BeanExpressionException for a service unit test. I found that setting that variable in my application.yml for the test environment solved my problem in Grails 4.

@Value in question:

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jeff Scott Brown
Solution 2 Lifeweaver