2012-02-03 75 views
12

我在Grails 2.0项目的一个服务中使用了一个用于国际化文本的消息包。用例是一个通过邮件插件以异步方式发送的电子邮件主题,所以将它放在控制器或TagLib中是没有意义的(考虑到通常不会访问服务中的文本或视图)。此代码在我运行的Grails应用程序中正常工作,但我不知道如何测试它。如何在Grails 2.0服务中为i18n注入messageSource的单元或集成测试使用

我想在我的defineBeans一个PluginAwareResourceBundleMessageSource,因为这是我运行的应用程序注入什么,但它导致了nullpointers,因为它似乎它需要大约插件经理一堆设置的并使得我的测试环境是不会放弃(甚至集成) 。

然后我尝试了一个ReloadableResourceBundleMessageSource,因为它是纯粹的Spring,但它似乎无法看到我的.properties文件,并且在代码'my.email.subject'下找不到用于语言环境'en'的No消息。

我觉得自己正在走下一个虫洞,因为访问服务中的Grails i18n没有记录在grails文档中,所以如果有一个首选的方法可以做到这一点,请告诉我。

注意我的.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);  
    } 
+0

是你的意图,以确保你在这个测试接线正确吗?还是你计划为你支持的每种语言写一篇文章?您的上述测试是单元测试还是集成测试? – 2012-02-03 20:09:34

+0

这个想法不是为了检查弹簧布线,而是在受到支持时测试各种语言,并检查.properties中关键字的正确性以及文本。为了可读性的目的,我简化了参数,但是测试了它们的正确性。 – Peter 2012-02-03 23:28:56

回答

27

已经有在Grails中单元测试为messageSource,它是一种的StaticMessageSource(见http://static.springsource.org/spring/docs/2.5.4/api/org/springframework/context/support/StaticMessageSource.html)时,可以与方法addMessage方法添加模拟消息:

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

谢谢,很高兴知道 - 是否可以使用StaticMessageSource和具有{0}样式占位符的消息来验证参数? – Peter 2012-02-04 20:54:58

+0

要回答我自己的评论,测试与占位符和伟大的作品。谢谢。 – Peter 2012-02-07 00:26:08

+3

我知道这个问题很老,但我发现让我走上正确的道路很有用。这是我嘲笑测试消息源的解决方案。首先,我得到了messageSource:'MessageSource messageSource = getMessageSource()' 确实messageSource在单元测试中,但是它是空的。所以我做了@Graem Rocher建议并为此测试填充messageSource与相关的消息。 'messageSource.addMessage(“messageService.sms.aNumber.recovery.message”,Locale.default,“{0},您的A编号为{1}”)' – CheddarMonkey 2015-05-06 19:09:28

2

在单元测试中,你可以确保你正确地做这样的有线了:

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”它返回“你好”,那么这对你不起作用。

+0

感谢您的想法。我不太关心弹簧布线,但我想加载我的实际Grails .properties文件(直接或通过Spring),而不是在测试中声明它,因为测试内容和密钥正确性是我想要的。 – Peter 2012-02-03 23:30:17

4

在单元测试和功能性的局部侧测试,有时候你需要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) 
相关问题