Spring Boot项目JUnit测试出现Thymeleaf SpringEL表达式异常
问题解决思路
核心原因
JUnit测试时没有模拟Spring Security的登录状态,导致Thymeleaf模板中#authentication对象为null,调用#authentication.principal.username时触发表达式求值异常。而手动测试时处于登录状态,Security上下文存在合法的Authentication对象,所以正常运行。
另外,手动配置WebMvcConfig添加Spring方言是多余操作——Spring Boot整合Thymeleaf+Spring Security时,已经自动注册了SpringSecurityDialect,手动配置反而可能破坏默认的模板解析逻辑,导致HTML文件无法访问。
解决方案
1. 修复JUnit测试:模拟登录状态
给测试方法添加Spring Security提供的注解,模拟登录用户,让Security上下文存在Authentication对象:
- 如果只是简单模拟用户,用
@WithMockUser:
@Test @WithMockUser(username = "test-user@example.com") // 填写和transaction.buddySender.email匹配的用户名 void shouldReturnHomePage() throws Exception { // 你的测试逻辑,示例: mockMvc.perform(get("/")) .andExpect(status().isOk()) .andExpect(view().name("home")); }
- 如果用了自定义
UserDetails实现,用@WithUserDetails(需要你的UserDetailsService能加载指定用户):
@Test @WithUserDetails(value = "test-user@example.com") void shouldReturnHomePage() throws Exception { // 测试逻辑 }
2. 模板表达式做Null安全处理(可选,增强健壮性)
即使模拟登录,也可以给Thymeleaf表达式加Null判断,避免极端场景下的报错:
<!-- 原表达式 --> <div th:if="#authentication.principal.username == transaction.buddySender.email">...</div> <!-- 修改为Null安全版本 --> <div th:if="${#authentication != null and #authentication.principal.username == transaction.buddySender.email}">...</div> <!-- 或者用Elvis简化写法 --> <div th:if="${(#authentication?.principal?.username) == transaction.buddySender.email}">...</div>
3. 恢复自动配置:删除自定义的WebMvcConfig方言配置
删掉你之前添加的SpringSecurityDialect Bean配置,让Spring Boot自动处理Thymeleaf方言注册,即可恢复HTML文件的访问:
// 删掉这段无用配置 @Bean public SpringSecurityDialect springSecurityDialect() { return new SpringSecurityDialect(); }
内容的提问来源于stack exchange,提问作者Kévin Jovanovic
相关产品推荐
相关产品推荐

