如何使用MockMvcBuilder将对象列表作为参数

时间:2017-06-24 12:20:51

标签: java spring-mvc

在我的Spring Boot项目中,我有一个名为AdminGameController的控制器,我想使用Springs MockMvcBuilder测试这些方法。这适用于处理GET请求的方法,但对于POST方法,需要Game对象作为参数,请参阅处理程序方法:

@RequestMapping(value = "/admin/game/save", method = RequestMethod.POST)
public String saveOrUpdate(@Valid Game game,
                   BindingResult bindingResult,
                   Model model,
                   RedirectAttributes redirectAttributes) {

    if (bindingResult.hasErrors()){
        model.addAttribute("message","Please fill in all necessary fields");
        addAttributes(model);
        return (game.getId()==0) ?
                   "admin/games/newGameForm" : "admin/games/editGameForm";
    }

    if(game.getTeams().size()>0 && 
       game.getTeams().get(0)!=null && 
       game.getTeams().get(1)!=null &&
              (game.getTeams().get(0).getId() ==
               game.getTeams().get(1).getId())) {
        model.addAttribute("message", "Teams cannot be the same. Try again");
        addAttributes(model);
        return (game.getId()==0) ? 
             "admin/games/newGameForm" : "admin/games/editGameForm";
    }

    if(game.getDate()!=null && game.getDate().before(new Date())) {
        model.addAttribute("message", "Date must be in the future. Try again");
        addAttributes(model);
        return (game.getId()==0) ? 
                 "admin/games/newGameForm" : "admin/games/editGameForm";
    }

    redirectAttributes.addFlashAttribute("message", 
       (game.getId()==0) ? 
                 "New game was created succesfully" : "Game was updated succesfully");
    gameService.save(game);
    return "redirect:/admin/games/page/1/date/asc";
}

为了测试这种方法,我写了以下测试:

@Test
public void saveNewGame() throws Exception{

    mockMvc.perform(post("/admin/game/save")
            .param("date", "01/10/2018")
            .param("teams", "1"))
            .andExpect(status().is3xxRedirection())
            .andExpect(view().name("redirect:/admin/games/page/1/date/asc"))
            .andExpect(
               MockMvcResultMatchers.
               flash().
               attribute("message", "New game was created succesfully"));

    ArgumentCaptor<Game> boundGame = ArgumentCaptor.forClass(Game.class);
    verify(gameService).save(boundGame.capture());

    Assert.assertEquals(DataLoader.parseDate("01/10/2018"), 
                        boundGame.getValue().getDate());
}

Spring会自动创建此Game对象,并将我添加到MockMvcBuilder的值作为参数映射到游戏对象的字段中。这一切都适用于原始数据类型和我上面使用的Data对象(String值完美地转换为Date对象,因为我使用模式注释了Date属性,请参阅Game bean下面的代码:

@Entity
public class Game {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

@NotNull
@ManyToMany (fetch = FetchType.EAGER)
private List<Team> teams = new ArrayList<>();

private Integer scoreTeamA;

private Integer scoreTeamB;

@ManyToOne
private Location location;

@ManyToOne
private Competition competition;

@NotNull
@DateTimeFormat(pattern="dd/MM/yyyy")
private Date date;

public Game(){}

//getters and setters and more
}

但是当想要给出一个团队对象列表时,这也是游戏对象的属性,我得到一个BindingResultError,它说:

  

org.springframework.validation.BeanPropertyBindingResult:1个错误   对象'团队'中对象'游戏'中的字段错误:被拒绝的值[1];   代码   [typeMismatch.game.teams,typeMismatch.teams,typeMismatch.java.util.List,typeMismatch];   参数   [org.springframework.context.support.DefaultMessageSourceResolvable:   代码[game.teams,teams];参数[];默认消息[团队]];   默认消息[无法转换类型的属性值   'java.lang.String'到属性的必需类型'java.util.List'   “团队”;嵌套异常是java.lang.IllegalStateException:不能   将'java.lang.String'类型的值转换为所需类型   'com.davidstranders.sportclub.model.Team'为财产'团队[0]':否   找到匹配的编辑器或转换策略]

上面我试图将teamId设置为teams对象的值,因为当用户在创建游戏对象时选择团队时会发生这种情况,请参阅模板(使用Thymeleaf):

 <div th:class="form-group" th:classappend="${#fields.hasErrors('teams')}? 'has-error'">
      <label class="col-md-3 control-label">
            Teams <span class="required">*</span>
      </label>
      <div class="col-md-9">
           <div class="col-md-5">
                <select class="form-control" th:field="*{teams}">
                    <option value="">Select team</option>
                    <option th:each="team : ${teams}" 
                            th:value="${team.id}" 
                            th:text="${team.name}">teams
                    </option>
                </select>
                <span th:if="${#fields.hasErrors('teams')}" 
                           th:errors="*{teams}"
                           th:class="help-block">Team Errors</span>
           </div>
           <div class="col-md-1"><label>vs</label></div>
           <div class="col-md-5">
                <select class="form-control" th:field="*{teams}">
                    <option value="">Select team</option>
                    <option th:each="team : ${teams}" 
                            th:value="${team.id}" 
                            th:text="${team.name}">teams
                    </option>
                </select>
                <span th:if="${#fields.hasErrors('teams')}" 
                      th:errors="*{teams}" 
                      th:class="help-block">Team Errors</span>
           </div>
      </div>
 </div>

有谁知道如何处理这个问题?我尝试将团队列为String,或团队实例为String,但这不起作用。

感谢您的帮助!!

0 个答案:

没有答案