如何在MockMVC帖子中将对象传递给ModelAttrbiute?

时间:2018-11-04 23:09:33

标签: java spring spring-mvc spring-test mockmvc

用户模型:

@Entity
@Table(name="user")
public class User {

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;

@NotBlank
@Column(name="username")
private String username;

@NotEmpty
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name="user_role", joinColumns = {@JoinColumn(name="user_id")},
                             inverseJoinColumns = {@JoinColumn(name="role_id")})
private Set<Role> roles;
}

控制器:

@RequestMapping(value = {"/users/edit/{id}"}, method = RequestMethod.POST)
public String editUser(ModelMap model, @Valid @ModelAttribute("user") User user, BindingResult result) {

    if(result.hasErrors()) {
        return "AddUserView";
    }

    return "redirect:/users";
}

使用MockMVC进行测试:

@Test
public void performUpdateUserTest() throws Throwable {
            mockMvc.perform(post("/users/edit/{id}", user.getId())
                   .param("username", "User"));
}

好吧,我可以像往常一样使用 param()传递参数用户名。但是我应该如何处理 ROLES ?该字段是一个单独的对象。我无法使用 param()传递它。那怎么可能通过考试呢?

我发现的唯一出路是创建一个实体并使用 .flashAttr()传递它:

    @Test
    public void performUpdateUserTest() throws Throwable {
          User user = new User("User", new HashSet<Role>(Arrays.asList(new Role("USER"))));
          mockMvc.perform(post("/users/edit/{id}", user.getId())
                 .flashAttr("user", user));
    }

但是,如果我需要测试用户是否由于 ROLES 字段中的绑定错误而无法更新(ROLES不能为null,并且假定将其设置为null),该怎么办? )?因此,由于绑定异常,我无法创建用户(并将其与.flashAttr结合使用),因为将引发异常。而且我仍然必须单独通过它。

1 个答案:

答案 0 :(得分:0)

好吧,经过长时间的搜索,我发现我应该在MockMVC中添加一个转换器。例如,您可以阅读HERE是什么转换器。 我已经在项目中使用了它,但没有意识到它不适用于MockMVC。

因此,您可以像这样将转换器添加到MockMVC:

    @Autowired
    private StringToRoleConverter stringToRoleConverter;

    @Before
    public void init() {
        FormattingConversionService cs = new FormattingConversionService();
        cs.addConverter(stringToRoleConverter);

        mockMvc = MockMvcBuilders.standaloneSetup(userController)
                .setConversionService(cs)
                .build();
    }

转换器本身:

@Component
public class StringToRoleConverter implements Converter<String, Role> {

    @Autowired
    private RoleService roleService;

    @Override
    public Role convert(String id) {
        Role role = roleService.findById(Integer.valueOf(id));

        return role;
    }

}

然后我可以像这样添加参数:

mockMvc.perform(post("/users/edit/{id}", user.getId())
        .param("roles", "2"))

尽管我在此处传递了一个字符串,但是它将在Spring转换器的帮助下转换为Role。