如何在 Grails 2.0 服务中对 i18n 注入 messageSource 的使用进行单元或集成测试
Posted
技术标签:
【中文标题】如何在 Grails 2.0 服务中对 i18n 注入 messageSource 的使用进行单元或集成测试【英文标题】:How to unit or integration test use of injected messageSource for i18n in Grails 2.0 service 【发布时间】:2012-02-26 10:01:00 【问题描述】:我在 Grails 2.0 项目中的一项服务中使用消息包来处理国际化文本。用例是通过邮件插件以异步方式发送的电子邮件主题,因此将其放在控制器或 TagLib 中确实没有意义(考虑到通常的论点是不访问服务中的文本或视图)。此代码在我正在运行的 Grails 应用程序中运行良好,但我不确定如何测试它。
我在我的 defineBeans 中尝试了PluginAwareResourceBundleMessageSource
,因为这是我正在运行的应用程序注入的内容,但它导致了空指针,因为它似乎需要围绕插件管理器进行大量设置,并且我的测试环境没有提供(甚至集成)。
然后我尝试了ReloadableResourceBundleMessageSource
,因为它是纯 Spring,但它似乎看不到我的 .properties 文件,并且失败并在代码 'my.email.subject' 下为语言环境“en”找到没有消息.
我觉得我正在进入一个虫洞,因为 grails 文档中没有记录在服务中访问 Grails i18n,所以如果有更好的方法可以做到这一点,请告诉我。
请注意,我的 .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 );
【问题讨论】:
您的意图是确保您已正确连接这一测试吗?或者您是否计划为您支持的每种语言编写一个?您的上述测试也是单元测试还是集成测试? 这个想法不是检查弹簧接线,而是更多地测试支持的各种语言,并检查 .properties 中的键和文本的正确性。为了可读性,我简化了参数,但需要测试它们的正确性。 【参考方案1】:Grails的单元测试中已经有一个messageSource,它是一个StaticMessageSource(见http://static.springsource.org/spring/docs/2.5.4/api/org/springframework/context/support/StaticMessageSource.html),你可以通过addMessage方法添加mock消息:
messageSource.addMessage("foo.bar", request.locale, "My Message")
【讨论】:
谢谢,很高兴知道 - 是否可以使用 StaticMessageSource 和带有 0 样式占位符的消息来验证参数? 回答我自己的评论,用占位符测试,效果很好。谢谢。 我知道这个问题很老,但我发现它有助于让我走上正轨。这是我模拟消息源以进行测试的解决方案。首先,我得到了 messageSource:MessageSource messageSource = getMessageSource()
messageSource 确实在单元测试中,但它是空的。所以我按照@Graem Rocher 的建议做了,并在 messageSource 中填充了该测试的相关消息。 messageSource.addMessage("messageService.sms.aNumber.recovery.message", Locale.default, "0, your A-Number is 1")
对于任何想知道它是否仍然适用的人。我已经用 Grails 3.2.5 对其进行了测试,并且效果很好。正如@Graeme 在他的回答中建议的那样,只需致电messageSource.addMessage
。
在 Grails 5.0.2 中不起作用。还有其他想法吗?【参考方案2】:
在单元测试和功能测试的本地方面,有时您需要 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)
【讨论】:
【参考方案3】:在单元测试中,您可以通过执行以下操作来确保正确连接:
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
这将有助于确保您正确连接,但不能确保您所做的事情确实有效。如果您对此感到满意,那么这对您有用。如果您尝试测试,当您将“XYZ”提供给您的 .properties 文件时,它会返回“Hello”,那么这对您不起作用。
【讨论】:
感谢您的想法。我不太关心弹簧接线,但我想加载我的实际 grails .properties 文件(直接或通过 Spring),而不是在测试中声明它,因为测试内容和密钥正确性是我想要的。以上是关于如何在 Grails 2.0 服务中对 i18n 注入 messageSource 的使用进行单元或集成测试的主要内容,如果未能解决你的问题,请参考以下文章