Spring Junit 5 的引导单元测试为什么模拟 return null
Spring boot unit test by Junit 5 why mock return null
这是我的控制器:-
@RestController
@RequestMapping(ScoreBoardController.REQUEST_URL)
public class ScoreBoardController {
public static final String REQUEST_URL = "/score";
public static final String POST_REQUEST = "/add";
public static final String GET_ALL_REQUEST = "/all";
public static final String DELETE_BY_ID = "/deleteById/{id}";
public static final String DELETE_BY_NAME = "/deleteByName/{name}";
public static final String DELETE_BY_ROUND_PATH_VAR = "/deleteByRoundPath/{round}";
public static final String DELETE_BY_ROUND_PARAM = "/deleteByRoundParam";
public static final String UPDAATE_NAME_BY_ID_PATH_VAR = "/updateNameByIdPath/{id}/{name}";
public static final String UPDATE_NAME_BY_ID_PARAM = "/updateNameByIdParam";
public static final String UPDATE_RESULT_BY_ID_PATH_VAR = "/updateResultByIdPath/{id}/{result}";
public static final String UPDATE_RESULT_BY_ID_PARAM = "/updateResultByIdParam";
public static final String GET_BY_ID = "/getById/{id}";
private ScoreService scoreService;
public ScoreBoardController(ScoreService scoreBoardService) {
this.scoreService = scoreBoardService;
}
@ApiOperation(value = "Add a new score post socre as json body")
@PostMapping(path = POST_REQUEST, produces = MediaType.APPLICATION_JSON_VALUE)
public Score save(
@ApiParam(value = "A score to save into db")
@RequestBody Score score) {
return scoreService.save(score);
}
}
服务:-
@Service
public class ScoreService {
@Autowired
private ScoreRepository scoreRepository;
public Score save(Score score) {
return scoreRepository.save(score);
}
}
如果 POST post 人
请求,它会起作用
http://localhost:8080/score/add
{
"name": "test4",
"round": 4,
"result": "WIN"
}
它在数据库中保存数据并且响应相同的分数。
但是我正在尝试按如下方式进行单元测试,但没有按预期工作。
@WebMvcTest({ScoreBoardController.class})
class ScoreBoardControllerTest {
@MockBean
private ScoreService scoreService;
@Autowired
private MockMvc mockMvc;
@Test
void save() throws Exception {
Score expectedScore = new Score(1l, "name", 1, Result.WIN, null);
String jsonScore = "{ \"id\": 1, \"name\": \"name\", \"round\" : 1, \"result\" : \"WIN\", \"timestamp\": null }";
when(scoreService.save(expectedScore)).thenReturn(expectedScore);
var ret = scoreService.save(expectedScore); // mock return correctly
mockMvc.perform( post(ScoreBoardController.REQUEST_URL+ScoreBoardController.POST_REQUEST)
.content(jsonScore)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1l))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("name"))
.andExpect(MockMvcResultMatchers.jsonPath("$.result").value("WIN"));
}
}
在上面的测试中,当我执行 post 请求时 scoreService.save(score) return null 而不是控制器代码中的模拟分数。为什么?怎么了?
mock returning null
意味着传递给 save()
的值不等于预期值。这就是我要尝试的:
- Score 是否正确实施
equals()
?
- 试试
when(scoreService.save(any())).thenReturn(expectedScore)
。无论参数如何,这应该始终 return expectedScore
。
- 尝试调试它并检查传递的分数实际是什么样子。
这是我的控制器:-
@RestController
@RequestMapping(ScoreBoardController.REQUEST_URL)
public class ScoreBoardController {
public static final String REQUEST_URL = "/score";
public static final String POST_REQUEST = "/add";
public static final String GET_ALL_REQUEST = "/all";
public static final String DELETE_BY_ID = "/deleteById/{id}";
public static final String DELETE_BY_NAME = "/deleteByName/{name}";
public static final String DELETE_BY_ROUND_PATH_VAR = "/deleteByRoundPath/{round}";
public static final String DELETE_BY_ROUND_PARAM = "/deleteByRoundParam";
public static final String UPDAATE_NAME_BY_ID_PATH_VAR = "/updateNameByIdPath/{id}/{name}";
public static final String UPDATE_NAME_BY_ID_PARAM = "/updateNameByIdParam";
public static final String UPDATE_RESULT_BY_ID_PATH_VAR = "/updateResultByIdPath/{id}/{result}";
public static final String UPDATE_RESULT_BY_ID_PARAM = "/updateResultByIdParam";
public static final String GET_BY_ID = "/getById/{id}";
private ScoreService scoreService;
public ScoreBoardController(ScoreService scoreBoardService) {
this.scoreService = scoreBoardService;
}
@ApiOperation(value = "Add a new score post socre as json body")
@PostMapping(path = POST_REQUEST, produces = MediaType.APPLICATION_JSON_VALUE)
public Score save(
@ApiParam(value = "A score to save into db")
@RequestBody Score score) {
return scoreService.save(score);
}
}
服务:-
@Service
public class ScoreService {
@Autowired
private ScoreRepository scoreRepository;
public Score save(Score score) {
return scoreRepository.save(score);
}
}
如果 POST post 人
请求,它会起作用http://localhost:8080/score/add
{
"name": "test4",
"round": 4,
"result": "WIN"
}
它在数据库中保存数据并且响应相同的分数。
但是我正在尝试按如下方式进行单元测试,但没有按预期工作。
@WebMvcTest({ScoreBoardController.class})
class ScoreBoardControllerTest {
@MockBean
private ScoreService scoreService;
@Autowired
private MockMvc mockMvc;
@Test
void save() throws Exception {
Score expectedScore = new Score(1l, "name", 1, Result.WIN, null);
String jsonScore = "{ \"id\": 1, \"name\": \"name\", \"round\" : 1, \"result\" : \"WIN\", \"timestamp\": null }";
when(scoreService.save(expectedScore)).thenReturn(expectedScore);
var ret = scoreService.save(expectedScore); // mock return correctly
mockMvc.perform( post(ScoreBoardController.REQUEST_URL+ScoreBoardController.POST_REQUEST)
.content(jsonScore)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").exists())
.andExpect(MockMvcResultMatchers.jsonPath("$.id").value(1l))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("name"))
.andExpect(MockMvcResultMatchers.jsonPath("$.result").value("WIN"));
}
}
在上面的测试中,当我执行 post 请求时 scoreService.save(score) return null 而不是控制器代码中的模拟分数。为什么?怎么了?
mock returning null
意味着传递给 save()
的值不等于预期值。这就是我要尝试的:
- Score 是否正确实施
equals()
? - 试试
when(scoreService.save(any())).thenReturn(expectedScore)
。无论参数如何,这应该始终 returnexpectedScore
。 - 尝试调试它并检查传递的分数实际是什么样子。