Spring Boot/Thymeleaf 单元测试:模型属性不存在 [英] Spring Boot/Thymeleaf Unit Test: Model attribute does not exist

查看:61
本文介绍了Spring Boot/Thymeleaf 单元测试:模型属性不存在的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个带有表单的视图,用户可以在其中输入 inputTemp 的值,并将输入保存在控制器的属性中.

查看:

<html xmlns:th="http://www.thymeleaf.org"><head th:include="fragments/template :: head"></head><头><title>智能简历</title><身体><nav th:replace="fragments/template :: header"></nav><div class="容器"><div class="hero-unit"><h1>Invoerscherm</h1>

<form action="#" th:action="@{/invoer}" th:object="${invoerscherm}" method="post"><td><input type="text" id="inputTemp" name="inputTemp" th:value="${inputTemp}"/></td><td><input name="submitKnop" type="submit" value="Input Temp"/></td></表单><nav th:replace="fragments/template::footer"></nav></html>

控制器:

@Controller公共类 InvoerschermController {私人字符串 inputTemp = "20";@GetMapping("/invoer")公共字符串 invoer(模型模型){model.addAttribute("inputTemp", getInputTemp());System.out.println("1:" + model.toString());返回 "invoerscherm";}@PostMapping("/invoer")公共字符串 addInputTemp(String inputTemp, 模型模型) {setInputTemp(inputTemp);model.addAttribute("inputTemp", getInputTemp());System.out.println("2:" + model.toString());尝试 {int newTemp = Integer.parseInt(getInputTemp());PostgresDatabase 数据库 = new PostgresDatabase();连接连接 = database.connectToDatabase();database.setTemperature(connection, newTemp);} catch (NumberFormatException nfe) {System.err.println("无效数字:" + nfe.getMessage());}返回 "invoerscherm";}公共字符串 getInputTemp() {返回输入温度;}public void setInputTemp(String inputTemp) {this.inputTemp = inputTemp;}}

现在,我想编写一个 UnitTest 来检查 inputTemp 是否正确保存.这些是我的单元测试:

@RunWith(SpringRunner.class)@WebMvcTest(InvoerschermController.class)@AutoConfigureMockMvc公共类 InvoerschermTest {@自动连线私有 MockMvc mockMvc;@测试公共无效 testCorrectModel() {尝试 {this.mockMvc.perform(get("/invoer", "20")).andExpect(status().isOk()).andExpect(model().attributeExists("inputTemp"));} 捕获(异常 e){e.printStackTrace();}}@测试公共无效 testPost() {尝试 {this.mockMvc.perform(post("/invoer", "20")).andExpect(status().isOk()).andExpect(view().name("invoerscherm"));} 捕获(异常 e){e.printStackTrace();}}@测试公共无效 testPostValueInModel() {尝试 {this.mockMvc.perform(post("/invoer", "20")).andExpect(status().isOk()).andExpect(model().attributeExists("inputTemp"));} 捕获(异常 e){e.printStackTrace();}}}

现在我的两个测试失败(testCorrectModel() 和 testPostValueInModel()),都带有以下消息:

java.lang.AssertionError:模型属性inputTemp"不存在

据我所知,该属性确实存在,所以我在某处做错了,我只是不知道我哪里出错了.看来我没有正确地将变量发送到 addInputTemp 方法.我该怎么做?

解决方案

在函数 testCorrectModel、testPostValueInModel 中模型属性的值为空,因为 inputTemp 的私有字段值在第一种情况下为空,在第二种情况下 String inputTemp 参数为空.

因此,在这些测试函数中,您实际上是在进行此调用

model.addAttribute("inputTemp", null);

地图的大小为 1,因为您在地图中添加了一个属性,但由于该属性的值为 null,model().attributeExists 将失败.

这里是spring框架中attributeExists的内部实现

public ResultMatcher attributeExists(final String... names) {返回新的 ResultMatcher() {公共无效匹配(MvcResult 结果)抛出异常 {ModelAndView mav = getModelAndView(result);for(字符串名称:名称){assertTrue("模型属性 '" + name + "' 不存在", mav.getModel().get(name) != null);}}};}

因此,正确设置 inputTemp 的值.例如对于 @RequestMapping("/invoer") 你如何设置 inputTemp 的值?在不同的功能?也许,您应该将其作为路径变量传递吗?

I have made a view with a form where the user can enter a value for inputTemp and the input is saved in an attribute in the Controller.

View:

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:include="fragments/template :: head"></head>
<head>
  <title>Smart CV</title>
</head>
<body>

<nav th:replace="fragments/template :: header"></nav>

<div class="container">
  <div class="hero-unit">
    <h1>Invoerscherm</h1>
  </div>
</div>

<form action="#" th:action="@{/invoer}" th:object="${invoerscherm}" method="post">
  <td><input type="text" id="inputTemp" name="inputTemp" th:value="${inputTemp}"/></td>
  <td><input name="submitKnop" type="submit" value="Input Temp"/></td>
</form>

<nav th:replace="fragments/template :: footer"></nav>
</body>
</html>

Controller:

@Controller
public class InvoerschermController {

    private String inputTemp = "20";

    @GetMapping("/invoer")
    public String invoer(Model model) {
        model.addAttribute("inputTemp", getInputTemp());
        System.out.println("1: " + model.toString());
        return "invoerscherm";
    }

    @PostMapping("/invoer")
    public String addInputTemp(String inputTemp, Model model) {
        setInputTemp(inputTemp);
        model.addAttribute("inputTemp", getInputTemp());
        System.out.println("2: " + model.toString());

        try {
            int newTemp = Integer.parseInt(getInputTemp());
            PostgresDatabase database = new PostgresDatabase();
            Connection connection = database.connectToDatabase();
            database.setTemperature(connection, newTemp);
        } catch (NumberFormatException nfe) {
            System.err.println("Invalid number: " + nfe.getMessage());
        }

        return "invoerscherm";
    }

    public String getInputTemp() {
        return inputTemp;
    }

    public void setInputTemp(String inputTemp) {
        this.inputTemp = inputTemp;
    }
}

Now, I want to write a UnitTest to check if the inputTemp is saved correctly. These are my unit tests for that:

@RunWith(SpringRunner.class)
@WebMvcTest(InvoerschermController.class)
@AutoConfigureMockMvc
public class InvoerschermTest {
    @Autowired
    private MockMvc mockMvc;    

    @Test
    public void testCorrectModel() {
        try {
            this.mockMvc.perform(get("/invoer", "20")).andExpect(status().isOk())
                    .andExpect(model().attributeExists("inputTemp"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testPost() {
        try {
            this.mockMvc.perform(post("/invoer", "20")).andExpect(status().isOk())
                    .andExpect(view().name("invoerscherm"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testPostValueInModel() {
        try {
            this.mockMvc.perform(post("/invoer", "20")).andExpect(status().isOk())
                    .andExpect(model().attributeExists("inputTemp"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Now two of my tests fail (testCorrectModel() and testPostValueInModel()), both with the following message:

java.lang.AssertionError: Model attribute 'inputTemp' does not exist

As far as I know, the attribute does exist, so somewhere I'm doing something wrong, and I just don't know where I'm going wrong. EDIT: it seems I am not sending the variable to the addInputTemp method correctly. How should I do this?

解决方案

in the functions testCorrectModel, testPostValueInModel the value of the model attribute is null since the private field value of inputTemp is null in the first case and in the second case the String inputTemp parameter is null.

Thus, in these tests functions you are actually making this call

model.addAttribute("inputTemp", null);

The size of the map is 1 because you have added an attribute in the map but the model().attributeExists would fail because the value of this attribute is null.

here is the internal implementation of attributeExists in spring framework

public ResultMatcher attributeExists(final String... names) {
        return new ResultMatcher() {
            public void match(MvcResult result) throws Exception {
                ModelAndView mav = getModelAndView(result);
                for (String name : names) {
                    assertTrue("Model attribute '" + name + "' does not exist", mav.getModel().get(name) != null);
                }
            }
        };
    }

Thus, set the value of the inputTemp correctly. For example for the @RequestMapping("/invoer") how do you set the value of inputTemp? In a different function? Maybe, should you pass it as a path variable?

这篇关于Spring Boot/Thymeleaf 单元测试:模型属性不存在的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
Java开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆