单元测试 Spring MVC 控制器:java.util.Map 数据未绑定



亲爱的开发人员在stackoverflow,

我非常感谢您帮助解决一个棘手的问题,我在对我的一个Spring MVC控制器进行单元测试时无法解决。

完整的代码存储库可以在这里找到:https://github.com/peerpub/peerpub

环境:

  • 爪哇 8
  • Maven 3.5
  • 弹簧启动 2.0.1
  • 弹簧框架 5.0.4
  • 百里香叶 3
  • JUnit 5 + Mockito

问题描述:

在尝试使用 Mockito/MockMVC 的单元测试方法对DocTypeAdminCtrl.java提出详细的测试时,我无法基于Map绑定数据,而简单的StringBoolean工作得很好。当我尝试在我的全栈集成测试中使用它(已经尝试过)时,也会发生同样的情况。

通过Web浏览器使用该应用程序时,不会出现此问题,因此这似乎完全与测试有关。

DocTypeAdminCtrlTest.java中名为editPost...()的所有测试都将失败。来自mvn test的示例日志摘录:

Tests run: 7, Failures: 3, Errors: 0, Skipped: 0, Time elapsed: 0.437 sec <<< FAILURE! - in de.fzj.peerpub.doc.doctype.DocTypeAdminCtrlTest
editPostFormSuccess  Time elapsed: 0.103 sec  <<< FAILURE!
java.lang.AssertionError: Status expected:<302> but was:<200>
at de.fzj.peerpub.doc.doctype.DocTypeAdminCtrlTest.editPostFormSuccess(DocTypeAdminCtrlTest.java:148)
editPostFormNonMatchingNames  Time elapsed: 0.046 sec  <<< FAILURE!
java.lang.AssertionError: Model attribute 'doctype' expected:   <DocTypeForm(name=vfAtXQ, displayName=01p14G7v22, system=false, multiDoc=true, attributes=[6Vuzhn, zKXSTl], mandatory={6Vuzhn=null, zKXSTl=true}, defaults={6Vuzhn=, zKXSTl=sooeOYb6Ld})> but was:<DocTypeForm(name=vfAtXQ, displayName=01p14G7v22, system=false, multiDoc=true, attributes=[6Vuzhn, zKXSTl], mandatory=null, defaults=null)>
at de.fzj.peerpub.doc.doctype.DocTypeAdminCtrlTest.editPostFormNonMatchingNames(DocTypeAdminCtrlTest.java:165)
editPostFormExceptionDTO  Time elapsed: 0.041 sec  <<< FAILURE!
java.lang.AssertionError: Model attribute 'doctype' expected:<DocTypeForm(name=GPzldO, displayName=mIV7Utta1Y, system=false, multiDoc=false, attributes=[8GsYhQ, bZGkd2], mandatory={8GsYhQ=null, bZGkd2=true}, defaults={8GsYhQ=SfoDlEiYAz, bZGkd2=k4uaLxx8yf})> but was:<DocTypeForm(name=GPzldO, displayName=mIV7Utta1Y, system=false, multiDoc=false, attributes=[8GsYhQ, bZGkd2], mandatory=null, defaults=null)>
at  de.fzj.peerpub.doc.doctype.DocTypeAdminCtrlTest.editPostFormExceptionDTO(DocTypeAdminCtrlTest.java:210)

请注意,属性mandatorydefaults始终设置为null,而存在于模型中。我已验证即使是我的自定义验证程序 DocTypeFormValidator.java 也没有看到此数据。这也导致我的editPostFormSuccess测试失败:由于属性设置为null,验证器不满意并且绑定结果包含错误。

当我单元/集成测试我的DocTypeAdminCtrl.java使用的任何类型的东西时,我很确定我的控制器类或测试类中一定缺少或错误。

MockMvcRequestBuilderUtils.postForm()中可能存在错误(请参阅上游),但我实际上不知道如何使用包含MapList的测试数据编写备用post()请求。使用调试器查看MockHttpServletRequestBuilder,似乎存在所有数据,包括mandatorydefaults,因此检查这可能是一件不太重要的事情......?

一些引起我注意的可疑调试日志输出行:

org.springframework.beans.BeanUtils - No property editor [java.util.MapEditor] found for type java.util.Map according to 'Editor' suffix convention
org.springframework.core.annotation.AnnotationUtils - Failed to meta-introspect annotation interface org.springframework.web.bind.annotation.ModelAttribute: java.lang.NullPointerException

在StackOverflow上和通过Google搜索这些错误并没有多大帮助... :-(

重现步骤:

只需克隆我的存储库,切换到我的功能分支oliver_dtsvc并运行mvn test

外面有人知道吗?任何帮助都非常感谢!

这完全与使用MockMvcRequestBuilderUtils.postForm()作为我的助手有关。

当我在editPostFormSuccess()中手动构建 POST 请求作为概念验证时,测试按预期运行:

ResultActions result = mvc.perform(post("/admin/doctypes/edit/{name}", this.valid.getName())
.param("name", this.valid.getName())
.param("displayName", this.valid.getDisplayName())
.param("system", this.valid.getSystem().toString())
.param("multiDoc", this.valid.getMultiDoc().toString())
.param("attributes[0]", this.valid.getAttributes().get(0))
.param("attributes[1]", this.valid.getAttributes().get(1))
.param("mandatory["+this.valid.getAttributes().get(0)+"]", this.valid.getMandatory().get(this.valid.getAttributes().get(0)).toString())
.param("mandatory["+this.valid.getAttributes().get(1)+"]", this.valid.getMandatory().get(this.valid.getAttributes().get(1)).toString())
.param("defaults["+this.valid.getAttributes().get(0)+"]", this.valid.getDefaults().get(this.valid.getAttributes().get(0)))
.param("defaults["+this.valid.getAttributes().get(1)+"]", this.valid.getDefaults().get(this.valid.getAttributes().get(1)))
);

所以我将尝试弄清楚如何扩展/改进MockMvcRequestBuilderUtils,因为它对构建这些请求有很大帮助。 上游问题:https://github.com/f-lopes/spring-mvc-test-utils/issues/3

相关内容

  • 没有找到相关文章

最新更新