Как передать объект в ModelAttrbiute в сообщении MockMVC? - PullRequest
0 голосов
/ 05 ноября 2018

Модель пользователя:

@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 , как всегда, используя 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 не может быть нулевым, и предположим, что оно было установлено как нулевое) ? Таким образом, я не могу создать пользователя (и использовать его с .flashAttr) уже с ошибкой привязки, поскольку будет выдано исключение. И я все еще должен передать это отдельно.

1 Ответ

0 голосов
/ 05 ноября 2018

Что ж, после долгого поиска я обнаружил, что должен добавить конвертер в MockMVC. Какой конвертер вы можете прочитать ЗДЕСЬ , например. У меня уже было это в моем проекте, но я не понимал, что это не работает с 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.

...