code-geek
code-geek

Reputation: 461

SpringBoot Unit test - Service method is not invoked

I am new to Unit Testing. After referring google, I created a Test class to test my Controller as follows:

@RunWith(SpringRunner.class)
@WebMvcTest(PromoController.class)
public class PromoApplicationTests {
    @Autowired
    protected MockMvc mvc;
    @MockBean PromoService promoService;
   
   
   protected String mapToJson(Object obj) throws Exception {
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.writeValueAsString(obj);
   }
   protected <T> T mapFromJson(String json, Class<T> clazz)
      throws JsonParseException, JsonMappingException, IOException {
      
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.readValue(json, clazz);
   }
   
   @Test
    public void applyPromotionTest_1() throws Exception {
           String uri = "/classPath/methodPath";
           List<Cart> cartLs = new ArrayList<Cart>();
          // added few objects to the list
           
           String inputJson = mapToJson(cartLs);
           MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
              .contentType(MediaType.APPLICATION_JSON).content(inputJson)).andReturn();
           
           int status = mvcResult.getResponse().getStatus();
           assertEquals(200, status);
           String actual = mvcResult.getResponse().getContentAsString();
           String expected = "{\"key1\":val1, \"key2\":\"val 2\"}";
           assertEquals(expected, actual, true);
            
    }
}

I have the following Controller and service Class :

@RequestMapping("/classPath")
@RestController
public class PromoController {
    @Autowired
    PromoService promoService;
    
    @PostMapping("/methodPath")
    public PromoResponse applyPromo(@RequestBody List<Cart> cartObj) {
        PromoResponse p = promoService.myMethod(cartObj);
        return p;
    }
}

@Component
public class PromoServiceImpl implements PromoService{

    @Override
    public PromoResponse myMethod(List<Cart> cartList) {
        // myCode
    }

}

When I debugged my unit test, p object in the controller was null. I am getting status as 200 but not the expected JSON response

What am I missing here?

Upvotes: 3

Views: 1210

Answers (1)

Ryuzaki L
Ryuzaki L

Reputation: 39978

While using @WebMvcTest spring boot will only initialize the web layer and will not load complete application context. And you need to use @MockBean to create and inject mock while using @WebMvcTest.

Which you have done

 @MockBean 
 PromoService promoService;

Spring Boot instantiates only the web layer rather than the whole context

We use @MockBean to create and inject a mock for the GreetingService (if you do not do so, the application context cannot start), and we set its expectations using Mockito.

But the, since it is mock bean you are responsible to mock the myMethod() call

@Test
public void applyPromotionTest_1() throws Exception {
       String uri = "/classPath/methodPath";
       List<Cart> cartLs = new ArrayList<Cart>();
      // added few objects to the list

      // create PromoResponse object you like to return
      When(promoService.myMethod(ArgumentsMatchesr.anyList())).thenReturn(/*PromoResponse object */);
       
       String inputJson = mapToJson(cartLs);
       MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
          .contentType(MediaType.APPLICATION_JSON).content(inputJson)).andReturn();
       
       int status = mvcResult.getResponse().getStatus();
       assertEquals(200, status);
       String actual = mvcResult.getResponse().getContentAsString();
       String expected = "{\"key1\":val1, \"key2\":\"val 2\"}";
       assertEquals(expected, actual, true);
        
}

Upvotes: 5

Related Questions