spring-webmvc/hibernate-validator 在测试期间不会使坏数据失效
Posted
技术标签:
【中文标题】spring-webmvc/hibernate-validator 在测试期间不会使坏数据失效【英文标题】:spring-webmvc/hibernate-validator not invalidating bad data during test 【发布时间】:2021-09-30 12:51:14 【问题描述】:我正在阅读 Spring In Action,并且正在研究 spring-mvc
的示例 spittr Web 应用程序。本书讨论了使用javax.annotation.constraints
来描述有效数据,例如
import javax.validation.constraints.*;
public class Spitter
@NotNull
@Size(min=5, max=16)
private String username;
//...
然后,它说,您可以将验证应用于使用 @Valid
装饰器作为参数的方法,例如
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
@Controller
@RequestMapping("/spitter")
public class SpitterController
@RequestMapping(value="/register", method=POST)
public String processRegistration(@Valid Spitter spitter, Errors errors)
if (errors.hasErrors())
return "registerForm";
return "redirect:/spitter/" + spitter.getUsername();
//...
为了检查我对材料的理解,我尝试编写一些测试来查看该方法对无效数据的反应:
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultBuilders.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
public class SpitterControllerTest
@Test
public void shouldNotProcessEmptyRegistration() throws Exception
standaloneSetup(new SpitterController())
.build()
.perform(post("/spitter/register"))
.andExpect(view().name("registerForm"));
@Test
public void shouldNotProcessInvalidRegistration() throws Exception
standaloneSetup(new SpitterController())
.build()
.perform(post("/spitter/register").param("username", "x"))
.andExpect(view().name("registerForm"));
//...
当测试失败时我很惊讶
shouldNotProcessEmptyRegistration(spittr.web.SpitterControllerTest) Time elapsed: 0.013 sec <<< FAILURE!
java.lang.AssertionError: View name expected:<registerForm> but was:<redirect:/spitter/null>
shouldNotProcessInvalidRegistration(spittr.web.SpitterControllerTest) Time elapsed: 0.013 sec <<< FAILURE!
java.lang.AssertionError: View name expected:<registerForm> but was:<redirect:/spitter/x>
我不知道我做错了什么。我知道测试时发生的事情与类路径上的内容有很大关系:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.13.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.0.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
我认为我可能遗漏了本书没有提及的一些依赖关系,但在这一点上,我并不确定自己做错了什么。
我通过谷歌搜索找到的大部分内容都在讨论 spring-boot,我现在正试图推迟它;在我开始尝试了解 spring-boot 带来什么之前,我想先了解 spring(但 Spring Boot In Action 是我的阅读清单上的下一个)。
我需要做些什么来修复我的代码,以便控制器在测试时成功检测到无效数据?
【问题讨论】:
【参考方案1】:似乎在您的代码中您要求 spitter 的用户名不能为空,但这并不意味着整个对象不能为空。在您当前的设置中,请求正文是可选的。你可以试试:
public String processRegistration(@RequestBody @Valid Spitter spitter, Errors errors)
默认情况下@RequestBody
要求正文。
【讨论】:
spitter
在此测试期间不是 null
,如果是 spitter.getUsername()
将抛出 NullPointerException
而不是返回 null
。我尝试按照您的指示添加 @RequestBody
装饰器,但这只是使测试失败,java.lang.AssertionError
即使给出了有效数据。
那我很糟糕,尽管我仍然看不到您的测试中的请求正文来自哪里。您提供的测试代码使它看起来像一个空的发布请求。
我将添加另一个测试以显示它对于非空但无效的用户名也失败以上是关于spring-webmvc/hibernate-validator 在测试期间不会使坏数据失效的主要内容,如果未能解决你的问题,请参考以下文章