当前位置: 首页 > 知识库问答 >
问题:

集成测试将整个对象发布到Spring MVC控制器

云欣嘉
2023-03-14

在集成测试Spring mvc Web应用程序时,有没有办法在模拟请求中传递整个表单对象?我所能找到的就是将每个字段单独作为参数传递,如下所示:

mockMvc.perform(post("/somehwere/new").param("items[0].value","value"));

这对于小形状很好。但是如果我发布的对象变大了怎么办?此外,如果我可以发布整个对象,那么测试代码看起来会更好。

具体来说,我想通过复选框测试多个项目的选择,然后发布它们。当然,我可以只测试发布一个项目,但我想知道。。

我们使用的是包含Spring-test-mvc的Spring 3.2.2。

我的表单模型如下所示:

NewObject {
    List<Item> selection;
}

我试过这样的电话:

mockMvc.perform(post("/somehwere/new").requestAttr("newObject", newObject) 

对于这样的控制器:

@Controller
@RequestMapping(value = "/somewhere/new")
public class SomewhereController {

    @RequestMapping(method = RequestMethod.POST)
    public String post(
            @ModelAttribute("newObject") NewObject newObject) {
        // ...
    }

但是对象将是空的(是的,我在测试中已经填充过)

我找到的唯一可行的解决方案是使用@SessionAttribute,比如:Spring MVC应用程序的集成测试:表单

但我不喜欢这样的想法,即必须记住在我需要的每个控制器的末尾调用complete。在所有表单数据都不必在会话中之后,我只需要为一个请求使用它。

因此,我现在唯一能想到的是编写一些Util类,它使用MockHttpServletRequestBuilder将所有对象字段附加为。参数使用反射或单独用于每个测试用例。。

我不知道,感觉不直观。。

有什么想法/想法可以让我的爱好变得更容易吗?(除了直接呼叫控制器)

谢谢

共有3个答案

弘康安
2023-03-14

我相信我已经找到了使用Spring Boot 1.4的最简单答案,包括测试类的导入

public class SomeClass {  /// this goes in it's own file
//// fields go here
}

import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.http.MediaType
import org.springframework.test.context.junit4.SpringRunner
import org.springframework.test.web.servlet.MockMvc

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status

@RunWith(SpringRunner.class)
@WebMvcTest(SomeController.class)
public class ControllerTest {

  @Autowired private MockMvc mvc;
  @Autowired private ObjectMapper mapper;

  private SomeClass someClass;  //this could be Autowired
                                //, initialized in the test method
                                //, or created in setup block
  @Before
  public void setup() {
    someClass = new SomeClass(); 
  }

  @Test
  public void postTest() {
    String json = mapper.writeValueAsString(someClass);
    mvc.perform(post("/someControllerUrl")
       .contentType(MediaType.APPLICATION_JSON)
       .content(json)
       .accept(MediaType.APPLICATION_JSON))
       .andExpect(status().isOk());
  }

}
谷梁楚青
2023-03-14

与MockMvc集成测试的主要目的之一是验证模型对象是否正确填充了表单数据。

为了做到这一点,您必须传递从实际表单传递的表单数据(使用.参数())。如果您使用从NewObject到数据的自动转换,您的测试将不会涵盖特定类别的可能问题(修改NewObject与实际表单不兼容)。

古起运
2023-03-14

我有同样的问题,结果证明,通过使用JSON marshaller,解决方案相当简单
让您的控制器通过将ModelAttribute(“newObject”)更改为RequestBody来更改签名。这样地:

@Controller
@RequestMapping(value = "/somewhere/new")
public class SomewhereController {

    @RequestMapping(method = RequestMethod.POST)
    public String post(@RequestBody NewObject newObject) {
        // ...
    }
}

然后在测试中,你可以简单地说:

NewObject newObjectInstance = new NewObject();
// setting fields for the NewObject  

mockMvc.perform(MockMvcRequestBuilders.post(uri)
  .content(asJsonString(newObjectInstance))
  .contentType(MediaType.APPLICATION_JSON)
  .accept(MediaType.APPLICATION_JSON));

其中asJsonString方法只是:

public static String asJsonString(final Object obj) {
    try {
        final ObjectMapper mapper = new ObjectMapper();
        final String jsonContent = mapper.writeValueAsString(obj);
        return jsonContent;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}  
 类似资料:
  • 我遵循了http://viralpatel.net/blogs/spring-mvc-multi-row-submit-java-list/将对象列表发布到我的Spring Controller。很快,当列表大小达到256时,我遇到了IndexOutOfBoundsException。 我找到了一个答案,它说在WebDataBinder中设置setAuto就可以解决这个问题。所以在我的控制器中,我

  • 我有一个复选框的集合,每个复选框代表一个“产品”的顶部。我想传递一个修改的产品对象,勾选的浇头存储为selectedToppings。 我已经尝试了下面的代码,但不起作用。问题是我正在传递一个空的“product”对象,并且只存储复选框值(作为“selectedToppings”)。如何将“product”对象与“selectedToppings”一起传递? html(片段): 控制器: 实体:

  • 当使用mockito单元测试Spring mvc控制器时,如何注入道层对象。当使用SpringJUnit4ClassRunner类时,它总是使用@Spy注释给空指针异常。 示例代码: 在这个测试用例中,依次调用,它总是返回

  • 问题内容: 我有一个定义了POST处理程序的控制器,如下所示: 以JSON格式查看时,UIVendor对象如下所示: UIVendor bean具有一个ArrayList类型的名为“ Emails”的字段,带有适当的设置器和获取器(getEmails / setEmails)。NotificationEmail对象也具有适当的公共设置器/获取器。 当我尝试使用以下代码发布对象时: 我在日志中收到此

  • 我的视图中有一个向控制器发送对象的表单,但问题是,如果我发送的对象超过256个,就会出现异常: 所以我在想为什么会有这样的限制,于是我找到了这个话题:https://stackoverflow.com/a/24699008/4173394 但它似乎对我不起作用(可能是我的一个坏习惯)。 下面是我的结构:我的视图名为createUpdate.vm,并像这样发布我的表单: 我在FollowerFile

  • 我有窗体和相应的控制器,对象列表被传递给它们。 实体类: 控制器: 形式: 我假设表单中的百里叶th:each循环变量不能是th:object=${ent2}(因为如果我这样做,select form返回null)。而th:value="${ent2.name}返回字符串值。所以我不得不将@RequestParam(th:value)发送给“save”方法。但是在这种情况下,我必须对数据库进行额外