2

I am currently writing a JUnit test case for a controller in my application which returns a object (a URL). I am trying to assert the expected and the actual URL to be the same. There are 2 things happening here when I inspect the MvcResult result:

  1. mockResponse has a status code of 200.

  2. In ModelAndView, the model does have the expected url value but when I try to assert the result using result.getResponse().getContentAsString(), the assertion fails as the result is empty.

What I have already tried:

  1. While debugging, I see the control moving to the service which means that the values were properly mocked and the expected url got returned to the result (as it was present in the ModelAndView when inspected).

  2. I have tried to give the expected url as a json object, used object mapper to read it and then tried a JSONAssert but the result is still empty.

    @RunWith(SpringJUnit4ClassRunner.class)
    public class StudentControllerTest {
    
      private static final String CACHE_URL= "cacheurl";
    
      @Mock
      StudentCacheService studentCacheService; 
    
      @InjectMocks
      StudentCacheController studentCacheController;
    
      private MockMvc mockMvc;
    
      @Before
      public void setUp() throws Exception {
      mockMvc = MockMvcBuilders.standaloneSetup(studentCacheController).build();
      }
    
      @Test
      public void testGetScoresUrl() throws Exception {
      Mockito.when(studentCacheService.getStudentUrl("123", "science"))
            .thenReturn(new StudentUrl(CACHE_URL));
      MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.get("/student/123/scores")
            .header("subject", "science").contentType(MediaType.APPLICATION_JSON)).andExpect(status().is2xxSuccessful())
            .andReturn();
      Assert.assertEquals(CACHE_URL, result.getResponse().getContentAsString());
      }
    } 
    

My Controller class is as below:

@Controller
@RequestMapping("/student")
public class StudentCacheController {
   @Autowired
   StudentCacheService studentCacheService;

   @GetMapping(path = "/{studentId}/scores",produces = MediaType.APPLICATION_JSON_VALUE)
   public StudentUrl getScores(@PathVariable String studentId, @RequestHeader(value = "subject", required = true) String subject) throws Exception {
    return studentCacheService.getStudentUrl(studentId, subject);
 }
}

The response is as below:

MockHttpServletResponse:
      Status = 200
      Error message = null
      Forwarded URL = student/123/scores
      Included URL = []

ModelAndView:
      model = ModelMap
        key = studentUrl
        value = StudentUrl
           url = "cacheurl" 

I am receiving this error : org.junit.ComparisonFailure: expected:<[cacheurl]> but was:<[]>

Any help appreciated. Thanks!

nehacharya
  • 925
  • 1
  • 11
  • 31
  • I could be wrong but for that piece of code, I can say that Mockito is not working as you expected. First, try to replace the class in RunWith for "MockitoJUnitRunner.class" and it's possible that you need EnableWebMvc too (https://stackoverflow.com/questions/19291329/enablewebmvc-annotation-meaning) – Cata Jun 21 '19 at 14:12
  • I tried both just now and it's still not working. – nehacharya Jun 21 '19 at 14:18
  • Can you add your controller class to see what are you trying to mock and tests?. I can't see from where your code obtain the "1" in the service call getStudentUrl("123", "1") – Cata Jun 21 '19 at 14:21
  • Sorry I forgot to change the "1" to the subject name. – nehacharya Jun 21 '19 at 14:33
  • what is the relation between FloorplanUrl and StudentUrl? – Cata Jun 21 '19 at 14:38
  • My mistake! I updated it. It's StudentUrl. – nehacharya Jun 21 '19 at 14:40
  • 1
    What I can tell you is the next: if you replace in the Controller the return type with ResponseEntity< StudentUrl > and return new ResponseEntity<>(studentUrl, HttpStatus.OK) you're going to receive {"url":"cacheurl"} as response. Now I'm trying to figure out why do you need to use that to give you a good answer. – Cata Jun 21 '19 at 14:57
  • A small change to your answer. I gave `ResponseEntity` and `return new ResponseEntity<>(studentUrl.getUrl(), HttpStatus.OK)` which worked since getUrl() returns a String but when I gave `ResponseEntity`, the response was an object of object and so the assertion failed for it. Thanks! – nehacharya Jun 21 '19 at 15:10
  • 2
    What was happening here is you didn't have a Response Body. You have to define one in order to receive something with your mvc. In order to get that you have 2 ways: add the annotation ResponseBody before the return type in the controller @ResponseBody StudentUrl getScores() or use ResponseEntity as a commented before. The difference between them is with the first you are defining an HTTP response and with the second you're using a kind of "default". You have more details here: https://stackoverflow.com/questions/26549379/when-use-responseentityt-and-restcontroller-for-spring-restful-applicati – Cata Jun 21 '19 at 15:16
  • Yes I understand now. Thanks! – nehacharya Jun 21 '19 at 15:19
  • simply adding ResponseBody fixed it for you? I'm getting a similar issue, but ResponseBody on the mapping does not fix it – RASMiranda Mar 15 '21 at 14:14
  • @salazarin please write an answer to your problem and mark it appropriately :) – payne Apr 13 '22 at 18:25

0 Answers0