Spring MVC集成测试:断言给定的模型属性有全局错误

logo-spring-io

为了使用Bean验证报告Spring MVC中的全局错误,我们可以创建一个自定义的类级别约束注释。 全局错误与已验证Bean中的任何特定字段都不相关。 在本文中,我将展示如何使用Spring Test编写测试,以验证给定的model属性是否存在全局验证错误。


自定义(类级别)约束

为了本文的方便,我创建了一个相对简单的类级别约束,称为SamePassword ,并由SamePasswordValidator进行了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 {};
}

如下所示,验证器非常简单:

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只是一个带有一些约束注释的POJO,包括我刚创建的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";}
}

当密码验证失败时,将在BindingResult (在上面的示例中为Errors中注册一个全局错误。 例如,我们可以在HTML页面的表单顶部显示此错误。 在Thymeleaf中,这将是:

<div th:if="${#fields.hasGlobalErrors()}"><p th:each="err : ${#fields.globalErrors()}" th:text="${err}">...</p>
</div>

集成测试与Spring Test

让我们设置一个集成测试:

@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();}
}

第一个测试验证发送带有空的表单passwordconfirmedPassword失败:

@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"));}

在上面的示例中,测试将验证password字段和confirmedPassword字段是否均存在字段错误。

同样,我想验证当给定的密码不匹配时,是否出现特定的全局错误。 因此,我期望这样的事情: .andExpect(model().hasGlobalError("passwordForm", "passwords do not match")) 。 不幸的是,由MockMvcResultMatchers#model()返回的ModelResultMatchers没有提供断言给定模型属性具有全局错误的方法。

由于不存在该匹配器,因此我创建了从ModelResultMatchers扩展的自己的匹配器。 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;}
}

通过上述添加,我现在可以验证全局验证错误,如下所示:

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"));
}

如您所见,扩展Spring Test的匹配器并提供给您自己的匹配器相对容易,可用于改进集成测试中的验证验证。

资源资源

  • 可以在这里找到本文的源代码: 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tips_一级菜单栏实现

1.纵向 1 <!DOCTYPE html>2 <html lang"en">3 <head>4 <meta charset"UTF-8">5 <title>menu01</title>6 <style type"text/css">7 *{8 margin: 0;9 pad…

2-使用git管理一个单片机程序

https://www.cnblogs.com/yangfengwu/p/10842205.html 我用电脑压缩一个文件,然后通过git上传,然后在新买的linux系统通过wget 网络下载这个压缩文件,然后死活解压不可以...无论是哪种格式的文件 一开始我怀疑是压缩软件压缩的问题,就换了一个压缩软件进行压缩,但是没有解决问题…

Java线程面试的前50个问题,面向初学者和经验丰富的程序员

您可以参加任何Java面试&#xff0c;无论是大四还是中级&#xff0c;经验或新来的人&#xff0c;一定会看到线​​程&#xff0c;并发和多线程中的几个问题。 实际上&#xff0c;这种内置的并发支持是Java编程语言的最强优势之一&#xff0c;并帮助它在企业界和程序员中同样流行…

《写给大家看的Web设计书(第3版)》即将上市

《写给大家看的设计书》姊妹篇——《写给大家看的Web设计书&#xff08;第3版&#xff09;》 即将上市。它是Robin Williams的又一本设计书。 也许大家对Robin Williams的畅销书《写给大家看的设计书》还念念不忘&#xff0c;还在回味那些简单凝练的设计经验。那好&#xff0c;…

VUE+ElementUI 搭建后台项目(一)

前言 之前有些过移动端的项目搭建的文章&#xff0c;感觉不写个pc端管理系统老感觉少了点什么&#xff0c;最近公司项目比较多&#xff0c;恰巧要做一个申报系统的后台管理系统&#xff0c;鉴于对vue技术栈比较熟悉&#xff0c;所以考虑还是使用vue技术栈来做&#xff1b;看过一…

用 .NET 3.5 创建 ToJSON() 扩展方法

今年早些时候&#xff0c;我通过blog介绍了 C# 和 VB 语言的一项新的扩充特性"扩展方法"。 扩展方法让开发者可以向已有的 CLR 类型的公共契约中添加新的方法&#xff0c;而不需要子类化或重新编译原有的类型。通过这种做法&#xff0c;可以使很多有用的应用场景成为…

Java中File的getPath(),getCanonicalPath()和getAbsolutePath()之间的区别

File API在Java中非常重要&#xff0c;因为它使文件系统可以访问Java程序。 尽管Java的文件API丰富&#xff0c;但是使用它们时仍需要了解许多细节。 关于文件路径的常见查询程序员之一是getPath() &#xff0c; getCanonicalPath()和getAbsolutePath()方法之间的区别&#xff…

Docker容器CPU、memory资源限制

背景 在使用 docker 运行容器时&#xff0c;默认的情况下&#xff0c;docker没有对容器进行硬件资源的限制&#xff0c;当一台主机上运行几百个容器&#xff0c;这些容器虽然互相隔离&#xff0c;但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制&…

JS_理解函数参数按值传递

本文是我基于红宝书《Javascript高级程序设计》中的第四章&#xff0c;4.1.3传递参数小节P70&#xff0c;进一步理解javaSript中函数的参数&#xff0c;当传递的参数是对象时的传递方式。 &#xff08;结合资料的个人理解&#xff0c;有不正确的地方&#xff0c;希望大家指出&…

检查Red Hat JBoss BRMS部署架构的规则和事件(第一部分)

&#xff08;文章来宾与北美红帽公司高级中间件顾问约翰赫洛克 &#xff08; John Hurlocker&#xff09;合着&#xff09; 在本周的技巧中&#xff0c;我们将放慢速度&#xff0c;并仔细研究可能的Red Hat JBoss BRMS部署体系结构。 当我们谈论部署架构时&#xff0c;我们指…

CSS_选择符

2016-10-28 《CSS入门经典》第五章 以下提示注意事项&#xff1a; 1.如何选择使用id选择符还是class选择符&#xff1a;当确信id选择符在页面的唯一性时&#xff0c;就可以使用id选择符。 2.通用选择符在所有元素上设置样式&#xff0c;并不是只设置继承的默认值。 eg&…

TFS2010配置SQLServer2008R2 tf255049错误

TFS2010配置SQLServer2008R2时&#xff0c;配置数据库时提示 tf255049错误。转载于:https://www.cnblogs.com/ShuaiHo/archive/2010/05/12/1733731.html

位运算笔记2.0

声明&#xff1a; 本文为转载文章 转载于:https://www.cnblogs.com/ShineEternal/p/10853132.html

教程–带有Jersey和Spring的Java REST API设计和实现

想要在Java中使用REST&#xff1f; 然后您来对地方了&#xff0c;因为在博客文章中&#xff0c;我将向您介绍如何“美丽”地设计REST API&#xff0c;以及如何使用Jersey框架在Java中实现它。 在本教程中开发的RESTful API将为存储在MySql数据库中的播客资源演示完整的Create&a…

ie6 下最佳 PNG透明方案【转】

“咳! 哎!….. ” 你听见了么? 这些都是大家抱怨IE6下不能实现png图片漂亮的明效果的哀叫声,的确是无奈呀….. 不过现在幸运的是,我们能够让这一切的抱怨都停止. 网络上解决IE6下Png透明解决方案有很多,例如 IE PNG Fix from TwinHelix, Javascript IE PNG Fix, Transparent …

安装svn、git等托管软件

安装软件&#xff0c;配置环境。下面我找到的别人写的&#xff0c;写的都很详细&#xff0c;做个记录。就不在这里写具体步骤了。 1.nodejs安装 使用vue-cli 搭建项目的时候需要nodejs&#xff0c;node是比较方便的&#xff0c;打包部署&#xff0c;解析vue单文件组件&#xff…

HBase:为客户行为生成搜索点击事件统计信息

在本文中&#xff0c;我们将探索HBase来存储客户搜索点击事件数据&#xff0c;并利用其基于搜索查询字符串和构面过滤器点击来获取客户行为信息。 我们将介绍如何使用MiniHBaseCluster&#xff0c;HBase Schema设计&#xff0c;使用HBaseSink与Flume集成以存储JSON数据。 在之…

WildFly 8.1.0.Final上的SwitchYard 2.0.0.Alpha1入门

最近&#xff0c;我一直在关注一些热门的RedHat技术&#xff0c;在其中很多有趣的部分中&#xff0c;我找到了SwitchYard 。 过去&#xff0c;对于所有人都围绕SOA和面向服务的体系结构不屑一顾&#xff0c;这对我来说一直很奇怪&#xff0c;作为Java EE开发人员。 过去&#…

zTree 优秀的jquery树插件

zTree 优秀的jquery树插件,文档详细&#xff0c;渲染快 使用方法&#xff1a; 1、引用zTree的js和css文件   <link href"~/Content/zTree_v3/css/zTreeStyle/zTreeStyle.css" rel"stylesheet" /><script src"~/Content/zTree_v3/js/jque…

Android 小項目之---Iphone拖动图片特效 (附源码)

曾经被Iphone用手指在屏幕上滑来滑去拖动图片的操作方式吸引吗&#xff1f;在Android里头&#xff0c;这并不是什么难事。 所需要的技术点如下&#xff1a;Android.content.Context 、Android.widget.BaseAdapter、Android.widget.ImageView等通常会用在设计相册、 图片类型的选…