javascript
Spring MVC集成测试:断言给定的模型属性有全局错误
為了使用Bean驗(yàn)證報(bào)告Spring MVC中的全局錯(cuò)誤,我們可以創(chuàng)建一個(gè)自定義的類級(jí)別約束注釋。 全局錯(cuò)誤與已驗(yàn)證Bean中的任何特定字段都不相關(guān)。 在本文中,我將展示如何使用Spring Test編寫測(cè)試,以驗(yàn)證給定的model屬性是否存在全局驗(yàn)證錯(cuò)誤。
自定義(類級(jí)別)約束
為了本文的方便,我創(chuàng)建了一個(gè)相對(duì)簡(jiǎn)單的類級(jí)別約束,稱為SamePassword ,并由SamePasswordValidator進(jìn)行了SamePasswordValidator :
@Target({TYPE, ANNOTATION_TYPE}) @Retention(RUNTIME) @Constraint(validatedBy = SamePasswordsValidator.class) @Documented public @interface SamePasswords {String message() default "passwords do not match";Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }如下所示,驗(yàn)證器非常簡(jiǎn)單:
public class SamePasswordsValidator implements ConstraintValidator<SamePasswords, PasswordForm> {@Overridepublic void initialize(SamePasswords constraintAnnotation) {}@Overridepublic boolean isValid(PasswordForm value, ConstraintValidatorContext context) {if(value.getConfirmedPassword() == null) {return true;}return value.getConfirmedPassword().equals(value.getPassword());} }PasswordForm只是一個(gè)帶有一些約束注釋的POJO,包括我剛創(chuàng)建的POJO:
@SamePasswords public class PasswordForm {@NotBlankprivate String password;@NotBlankprivate String confirmedPassword;// getters and setters omitted for redability}@Controller
控制器有兩種方法:顯示表單和處理表單的提交:
@Controller @RequestMapping("globalerrors") public class PasswordController {@RequestMapping(value = "password")public String password(Model model) {model.addAttribute(new PasswordForm());return "globalerrors/password";}@RequestMapping(value = "password", method = RequestMethod.POST)public String stepTwo(@Valid PasswordForm passwordForm, Errors errors) {if (errors.hasErrors()) {return "globalerrors/password";}return "redirect:password";} }當(dāng)密碼驗(yàn)證失敗時(shí),將在BindingResult (在上面的示例中為Errors中注冊(cè)一個(gè)全局錯(cuò)誤。 例如,我們可以在HTML頁(yè)面的表單頂部顯示此錯(cuò)誤。 在Thymeleaf中,這將是:
<div th:if="${#fields.hasGlobalErrors()}"><p th:each="err : ${#fields.globalErrors()}" th:text="${err}">...</p> </div>集成測(cè)試與Spring Test
讓我們?cè)O(shè)置一個(gè)集成測(cè)試:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public class AccountValidationIntegrationTest {@Autowiredprivate WebApplicationContext wac;private MockMvc mockMvc;@Beforepublic void setUp() throws Exception {mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();} }第一個(gè)測(cè)試驗(yàn)證發(fā)送帶有空的表單password和confirmedPassword失敗:
@Testpublic void failsWhenEmptyPasswordsGiven() throws Exception {this.mockMvc.perform(post("/globalerrors/password").param("password", "").param("confirmedPassword", "")).andExpect(model().attributeHasFieldErrors("passwordForm", "password", "confirmedPassword")).andExpect(status().isOk()).andExpect(view().name("globalerrors/password"));}在上面的示例中,測(cè)試將驗(yàn)證password字段和confirmedPassword字段是否均存在字段錯(cuò)誤。
同樣,我想驗(yàn)證當(dāng)給定的密碼不匹配時(shí),是否出現(xiàn)特定的全局錯(cuò)誤。 因此,我期望這樣的事情: .andExpect(model().hasGlobalError("passwordForm", "passwords do not match")) 。 不幸的是,由MockMvcResultMatchers#model()返回的ModelResultMatchers沒有提供斷言給定模型屬性具有全局錯(cuò)誤的方法。
由于不存在該匹配器,因此我創(chuàng)建了從ModelResultMatchers擴(kuò)展的自己的匹配器。 Java 8版本的代碼如下:
public class GlobalErrorsMatchers extends ModelResultMatchers {private GlobalErrorsMatchers() {}public static GlobalErrorsMatchers globalErrors() {return new GlobalErrorsMatchers();}public ResultMatcher hasGlobalError(String attribute, String expectedMessage) {return result -> {BindingResult bindingResult = getBindingResult(result.getModelAndView(), attribute);bindingResult.getGlobalErrors().stream().filter(oe -> attribute.equals(oe.getObjectName())).forEach(oe -> assertEquals("Expected default message", expectedMessage, oe.getDefaultMessage()));};}private BindingResult getBindingResult(ModelAndView mav, String name) {BindingResult result = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + name);assertTrue("No BindingResult for attribute: " + name, result != null);assertTrue("No global errors for attribute: " + name, result.getGlobalErrorCount() > 0);return result;} }通過上述添加,我現(xiàn)在可以驗(yàn)證全局驗(yàn)證錯(cuò)誤,如下所示:
import static pl.codeleak.demo.globalerrors.GlobalErrorsMatchers.globalErrors;@Test public void failsWithGlobalErrorWhenDifferentPasswordsGiven() throws Exception {this.mockMvc.perform(post("/globalerrors/password").param("password", "test").param("confirmedPassword", "other")).andExpect(globalErrors().hasGlobalError("passwordForm", "passwords do not match")).andExpect(status().isOk()).andExpect(view().name("globalerrors/password")); }如您所見,擴(kuò)展Spring Test的匹配器并提供給您自己的匹配器相對(duì)容易,可用于改進(jìn)集成測(cè)試中的驗(yàn)證驗(yàn)證。
資源資源
- 可以在這里找到本文的源代碼: https : //github.com/kolorobot/spring-mvc-beanvalidation11-demo 。
翻譯自: https://www.javacodegeeks.com/2014/08/spring-mvc-integration-testing-assert-the-given-model-attributes-have-global-errors.html
總結(jié)
以上是生活随笔為你收集整理的Spring MVC集成测试:断言给定的模型属性有全局错误的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是雁鹅(明年养这种雁鹅前景还是很可观
- 下一篇: Java线程面试的前50个问题,面向初学