Spring 使用 Freemarker 启动应用程序的单元测试抛出 NoSuchMessageException

Unit testing of Spring Boot application with Freemarker throws NoSuchMessageException

我正在开发一个使用 FreeMarker 作为模板引擎的 Spring Boot Web 应用程序。
我有 1.4.0 版本的 spring-boot 并使用自动配置,有国际化和很少的 messages.properties 用于不同的语言环境。一切正常,取决于 FreeMarker 生成的当前语言环境应用程序 returns HTML 并填充了来自适当 .properties.

的字符串

但是当我尝试测试正确工作的控制器时,我得到 NoSuchMessageException,FreeMarker 无法在 messages.properties 中找到字符串。

我按照下面的文章实现了单元测试Testing improvements in Spring Boot 1.4

测试代码如下:

@RunWith(SpringRunner.class)
@WebMvcTest(VideoController.class)
public class VideoControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    VideoService videoService;

    @Test
    public void showVideoSection() throws Exception {
        ResultActions result = mockMvc.perform(MockMvcRequestBuilders.get("/video"));
        result.andExpect(MockMvcResultMatchers.view().name("video"));
    }

}

这里是测试方法的代码:

 @RequestMapping(value = "/video", method = RequestMethod.GET)
 public String showVideoSection(Model model) {
    model.addAttribute("currentLanguage", LocaleContextHolder.getLocale().getLanguage());
    long numberOfAvailableVideos = videoService.getNumberOfAvailableVideos();
    if (numberOfAvailableVideos > 0) {
        if (numberOfAvailableVideos >= 5) {
            model.addAttribute("videoList", videoService.getPageOfVideos(0, 5));
        } else {
            model.addAttribute("videoList", videoService.getPageOfVideos(0, (int)numberOfAvailableVideos));
        }
    } 
    return "video";
}

下面是堆栈跟踪:

2016-08-10 17:07:32.210 ERROR 5504 --- [main] freemarker.runtime: Error executing FreeMarker template

freemarker.core._TemplateModelException: Java method "org.springframework.web.servlet.support.RequestContext.getMessage(String)" threw an exception when invoked on org.springframework.web.servlet.support.RequestContext object "org.springframework.web.servlet.support.RequestContext@4da6d664"; see cause exception in the Java stack trace.

----
FTL stack trace ("~" means nesting-related):
- Failed at: ${springMacroRequestContext.getMessag...  [in template "spring.ftl" in macro "message" at line 28, column 22]
- Reached through: @spring.message code="nav.video"  [in template "common.ftl" in macro "body" at line 65, column 49]
- Reached through: @common.body mode="video" language="$...  [in template "video.ftl" at line 7, column 5] 
~ Reached through: #nested  [in template "common.ftl" in macro "html" at line 12, column 5] 
~ Reached through: @common.html  [in template "video.ftl" at line 5, column 1]
----

...
...
Caused by: org.springframework.context.NoSuchMessageException: No message found under code 'nav.video' for locale 'en'.
at org.springframework.context.support.DelegatingMessageSource.getMessage(DelegatingMessageSource.java:69) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getMessage(AbstractApplicationContext.java:1254) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.support.RequestContext.getMessage(RequestContext.java:711) ~[spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.web.servlet.support.RequestContext.getMessage(RequestContext.java:677) ~[spring-webmvc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_77]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_77]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_77]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_77]
at freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:1458) ~[freemarker-2.3.25-incubating.jar:2.3.25]
at freemarker.ext.beans.ReflectionCallableMemberDescriptor.invokeMethod(ReflectionCallableMemberDescriptor.java:56) ~[freemarker-2.3.25-incubating.jar:2.3.25]
at freemarker.ext.beans.MemberAndArguments.invokeMethod(MemberAndArguments.java:51) ~[freemarker-2.3.25-incubating.jar:2.3.25]
at freemarker.ext.beans.OverloadedMethodsModel.exec(OverloadedMethodsModel.java:61) ~[freemarker-2.3.25-incubating.jar:2.3.25]
... 79 common frames omitted

我最好的猜测是 MessageSourceAutoConfiguration 需要 运行 才能正确处理 message.properties 文件。目前情况可能并非如此(我们应该在 Spring Boot 1.4.1 中修复一些问题)。

您可以通过添加包含以下内容的 src/test/resources/META-INF/spring.factories 文件来解决此问题:

org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc=\
org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration

我已经提出 https://github.com/spring-projects/spring-boot/issues/6608 来解决这个问题。如果您有一个复制该问题的示例项目,请将 link 附加到错误报告中。