简体   繁体   中英

Spring boot unit test by Junit 5 why mock return null

Here is my controller:-

@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:-

@Service
public class ScoreService {

    @Autowired
    private ScoreRepository scoreRepository;

    public Score save(Score score) {
       return scoreRepository.save(score);
    }
}

It works if I POST request by the postman

http://localhost:8080/score/add

{
    "name": "test4",
    "round": 4,
    "result": "WIN"
}

It saves the data in DB and response same score.

But I am trying to unit test as follows that doesn't work as expected.

@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"));
    }
}

On the above test when I perform post request scoreService.save(score) return null instead of mocked score in the controller code. Why? What is wrong?

The mock returning null means that the values passed to save() is not equal to the expected value. This is what I would try:

  1. Is Score implementing equals() correctly?
  2. Try with when(scoreService.save(any())).thenReturn(expectedScore) . This should always return expectedScore regardless of the parameter.
  3. Try to debug it and check what the passed Score actually looks like.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM