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 附加到错误报告中。
我正在开发一个使用 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 附加到错误报告中。