在我的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,但这不起作用。
感谢您的帮助!!