2012-02-03 77 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) 
相關問題