【问题标题】:How to pass an object to a ModelAttrbiute in MockMVC post?如何在 MockMVC 帖子中将对象传递给 ModelAttrbiute?
【发布时间】:2018-11-04 23:09:32
【问题描述】:

用户模型:

@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() 传递参数 username。但是我应该如何处理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 不能为空,并且假设它被设置为空)?因此,我无法创建带有绑定错误的用户(并将其与 .flashAttr 一起使用),因为将引发异常。而且我还是要分开过。

【问题讨论】:

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


    【解决方案1】:

    嗯,找了半天,发现应该在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 转换器的帮助下转换为角色。

    【讨论】:

      猜你喜欢
      • 2022-11-02
      • 2014-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      • 1970-01-01
      相关资源
      最近更新 更多