Testing 如何在Grails2.0服务中对i18n注入messageSource的使用进行单元或集成测试

Testing 如何在Grails2.0服务中对i18n注入messageSource的使用进行单元或集成测试,testing,grails,service,internationalization,grails-2.0,Testing,Grails,Service,Internationalization,Grails 2.0,我在Grails2.0项目中的一个服务中使用了一个消息包,用于国际化文本。用例是一个通过邮件插件以异步方式发送的电子邮件主题,因此在控制器或TagLib中使用它是没有意义的(考虑到不在服务中访问文本或视图的常见参数)。这段代码在我运行的Grails应用程序中运行良好,但我不确定如何测试它 我在我的定义中尝试了一个PluginAwareResourceBundleMessageSource,因为这是我正在运行的应用程序注入的内容,但它导致了空指针,因为它似乎需要围绕插件管理器进行一系列设置,因此我

我在Grails2.0项目中的一个服务中使用了一个消息包,用于国际化文本。用例是一个通过邮件插件以异步方式发送的电子邮件主题,因此在控制器或TagLib中使用它是没有意义的(考虑到不在服务中访问文本或视图的常见参数)。这段代码在我运行的Grails应用程序中运行良好,但我不确定如何测试它

我在我的定义中尝试了一个
PluginAwareResourceBundleMessageSource
,因为这是我正在运行的应用程序注入的内容,但它导致了空指针,因为它似乎需要围绕插件管理器进行一系列设置,因此我的测试环境无法提供(甚至集成)

然后我尝试了一个
reloadableSourceBundleMessageSource
,因为它是纯Spring,但它似乎看不到我的.properties文件,并且失败了,在区域设置“en”的代码“my.email.subject”下找不到任何消息

我觉得我有点像虫洞,因为Grails文档中没有记录在服务中访问Grails i18n,所以如果有更好的方法,请告诉我

注意my.properties文件位于标准的
grails app/i18n
位置

测试

@TestFor(EmailHelperService)
class EmailHelperServiceTests {

    void testSubjectsDefaultLocale() {
        defineBeans {
            //messageSource(PluginAwareResourceBundleMessageSource); Leads to nullpointers
            messageSource(ReloadableResourceBundleMessageSource);

        }
        String expected = "My Expected subject Passed1 Passed2";
        String actual = service.getEmailSubjectForStandardMustGiveGiftFromBusiness(Locale.ENGLISH, Passed1 Passed2);
        assertEquals("email subject", expected, actual);

}
服务:

    class EmailHelperService {
    def messageSource;

    public String getEmailSubject(Locale locale, String param1, String param2) {
        Object[] params = [param1, param2].toArray();      
        return messageSource.getMessage("my.email.subject", params, locale );      
    }

在单元测试中,您可以通过执行以下操作来确保连接正确:

void testSubjectsDefaultLocale() {
    def messageSource = new Object()
    messageSource.metaClass.getMessage = {subject, params, locale ->
        assert "my.email.subject" == subject
        assert ["Passed1", "Passed2"] == params 
        assert Locale.ENGLISH == locale
        "It Worked!!!"
    }
    service.messageSource = messageSource
    String actual = service.getEmailSubjectForStandardMustGiveGiftFromBusiness(Locale.ENGLISH, Passed1 Passed2)
    assert "It Worked!!!" == actual
}

这将有助于确保您正确连接,但无法确保您所做的实际工作正常。如果你对此感到满意,那么这将对你有用。如果您试图在为.properties文件指定“XYZ”时进行测试,它将返回“Hello”,那么这将不适用于您。

Grails中的单元测试中已经有一个messageSource,它是一个StaticMessageSource(请参阅),您可以使用addMessage方法添加模拟消息:

messageSource.addMessage("foo.bar", request.locale, "My Message")

在单元测试和功能测试的本地端中,有时您需要18n目录中的真实属性

这对我很有用:

  MessageSource getI18n() {
    // assuming the test cwd is the project dir (where application.properties is)
    URL url = new File('grails-app/i18n').toURI().toURL()
    def messageSource = new ResourceBundleMessageSource()
    messageSource.bundleClassLoader = new URLClassLoader(url)
    messageSource.basename = 'messages'
    messageSource
  }

  i18n.getMessage(key, params, locale)

您的目的是确保您正确地连接了这一测试吗?或者你打算为你所支持的每种语言写一本?您上面的测试也是单元测试还是集成测试?其目的不是检查spring连接,而是在各种语言得到支持时测试它们,并检查.properties和文本中键的正确性。为了可读性,我简化了参数,但需要测试它们的正确性。谢谢你的想法。我不太关心spring的连接,但我希望加载实际的grails.properties文件(直接加载或通过spring加载),而不是在测试中声明它,因为测试内容和密钥的正确性是我想要的。谢谢,很高兴知道-是否可以使用StaticMessageSource和带有{0}样式的占位符?为了回答我自己的评论,使用占位符进行了测试,效果很好。谢谢。我知道这个问题很老,但我发现它很有用,可以帮助我找到正确的方向。下面是我模拟消息源进行测试的解决方案。首先,我得到了消息源:
messageSource messageSource=getMessageSource()
messageSource确实在单元测试中,但它是空的。所以我按照@Graem Rocher的建议做了,并为messageSource填充了此测试的相关消息。
messageSource.addMessage(“messageService.sms.aNumber.recovery.message”,Locale.default,“{0},您的A号是{1}”)
任何想知道它是否仍然适用的人。我已经用Grails 3.2.5对它进行了测试,它工作得很好。只需按@Graeme在回答中的建议调用
messageSource.addMessage