Grails Locale not set for Spock unit tests

In my Grails 2.2 application I make some calculations which requires Locale to be set correctly. Therefore I provide this configuration block in my application, as mentioned elsewhere.

grails-app/config/spring/resources.groovy:

beans = {
    localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
        defaultLocale = new Locale("da","DK")
        java.util.Locale.setDefault(defaultLocale)
    }
}

Now, as also suggested by other questions and answers, this works in my context for the running application but not for unit tests.

I made this snippet to verify (on a page in the application):

<h2>Locale settings</h2>
<p>The following properties relevant to Locale is configured:</p>
<pre>
LocaleContextHolder.locale:              '${org.springframework.context.i18n.LocaleContextHolder.locale}'
java.util.Locale.getDefault():           '${java.util.Locale.getDefault()}'
RequestContextUtils.getLocale(request):  '${org.springframework.web.servlet.support.RequestContextUtils.getLocale(request)}'
session['SessionLocaleResolver.LOCALE']: '${session['org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE']}'
</pre>

which renders

Locale settings

The following properties relevant to Locale is configured:

LocaleContextHolder.locale:              'da_DK'
java.util.Locale.getDefault():           'da_DK'
RequestContextUtils.getLocale(request):  'da_DK'
session['SessionLocaleResolver.LOCALE']: '' 

But for unit testing it does not work

The problem occurs for my unit test (I need java.util.Calendar weeks to start on Mondays (default for da_DK, but the week starts on Sunday (default for en_* locales).

In this case I made two test cases:

In test/unit/DefaultLocaleSpec.groovy:

import grails.test.mixin.TestMixin
import grails.test.mixin.web.ControllerUnitTestMixin
import org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletRequest
import org.springframework.web.servlet.support.RequestContextUtils
import spock.lang.Specification

@TestMixin(ControllerUnitTestMixin)
class DefaultLocaleSpec extends Specification {

    // ---------------------------------
    //       Locale verification (affects java Calendar calculations)
    // ---------------------------------
    def "locale (request) should be set to Danish, so that week starts Monday"() {
        given:
        GrailsMockHttpServletRequest request = new GrailsMockHttpServletRequest()
        when:
        Locale result = RequestContextUtils.getLocale(request)
        then:
        result == new Locale("da", "DK")
    }

    def "locale (default) should be set to Danish, so that week starts Monday"() {
        when:
        Locale result = java.util.Locale.getDefault()

        then:
        result == new Locale("da", "DK")
    }

The two tests fail with the following messages:

Condition not satisfied:

result == new Locale("da", "DK")
|      |  |
en     |  da_DK
       false

    at DefaultLocaleSpec.locale (request) should be set to Danish, so that week starts Monday(DefaultLocaleSpec.groovy:27)


Condition not satisfied:

result == new Locale("da", "DK")
|      |  |
en_US  |  da_DK
       false
 <Click to see difference>

    at DefaultLocaleSpec.locale (default) should be set to Danish, so that week starts Monday(DefaultLocaleSpec.groovy:35)

One workaround I found was to add the following to the unit test file:

def setupSpec() {
    java.util.Locale.setDefault(new Locale("da", "DK"))
}

I feel tempted to pick that as a solution, but then I may have to add it to all my unit test file to fix the locale. And it seems like repeated work. I prefer my code more DRY (don’t repeat yourself).

Option to change my machine’s default Locale.

This I like to avoid, since everything I have to do to modify my setup, my colleagues also have to learn. Less customization is better. The more I can put inside the application, the better for me, my colleagues and any maintainers of the code 🙂

Question

This pinpoints my actual problem: I want to set up correct (default) locale also for the unit testing environment. How to do that – in a DRY way?

I prefer to make one change in one file which globally affects my app.

Related questions

These related questions do not quite answer or solve my problem (but have related ideas)


Source: java

Leave a Reply