Junit test cases for API's I'm new to Junit and Mockito, trying to write unit test cases for my controller class to test my APIs. Here is the controller class
package com.mylearnings.controller;
import com.mylearnings.modal.Product;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@RestController
public class ProductController {
private HashMap<String, Product> productCatalog = new HashMap<>();
@PostMapping("/product")
public ResponseEntity addProduct(@RequestBody Product product) {
productCatalog.put(product.getId(), product);
return new ResponseEntity("product added successfully", HttpStatus.CREATED);
}
@GetMapping("/product/{id}")
public ResponseEntity getProductDetails(@PathVariable String id) {
return ResponseEntity.ok(productCatalog.get(id));
}
@GetMapping("/product")
public List<Product> getProductList() {
return new ArrayList<>(productCatalog.values());
}
@PutMapping("/product")
public String updateProduct(@RequestBody Product product) {
productCatalog.put(product.getId(), product);
return "product updated successfully";
}
@DeleteMapping("/product/{id}")
public String deleteProduct(@PathVariable String id) {
productCatalog.remove(id);
return "product deleted successfully";
}
}
I have tried the following Added @ExtendWith(MockitoExtension.class) and tried but still it's failing
package com.mylearnings.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mylearnings.modal.Product;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.web.context.WebApplicationContext;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
@SpringBootTest
@AutoConfigureMockMvc
public class ProductControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Mock
private Map<String, Product> productCatalog;
@InjectMocks
private ProductController productController;
@Test
public void testAddProduct() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/product").contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(new Product("MS116", "Dell MS116", "Dell MS116 Usb wired optical mouse", "", 229d)))).andReturn();
assertEquals(201, mvcResult.getResponse().getStatus());
}
@Test
public void testGetProductDetails() throws Exception {
Product product = new Product("MS116", "Dell MS116", "Dell MS116 Usb wired optical mouse", "", 229d);
when(productCatalog.get("MS116")).thenReturn(product);
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/product/{id}", "MS116").accept(MediaType.APPLICATION_JSON)).andReturn();
assertEquals(200, mvcResult.getResponse().getStatus());
Product result = new ObjectMapper().readValue(mvcResult.getResponse().getContentAsString(), Product.class);
assertEquals(product, result);
}
}
the test case testGetProductDetails() is failing, I'm not sure whether it is because of map?
CodePudding user response:
In order to be able to inject mocks into Application context using (@Mock
and @InjectMocks
) and make it available for you MockMvc
, you can try to init MockMvc
in the standalone mode with the only ProductController
instance enabled (the one that you have just mocked).
Example:
package com.mylearnings.controller;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import com.mylearnings.controller.Product;
import com.mylearnings.controller.ProductController;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@ExtendWith(MockitoExtension.class)
public class ProductControllerTest {
private MockMvc mockMvc;
@Mock
private HashMap<String, Product> productCatalog;
@InjectMocks
private ProductController productController;
@BeforeEach
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(productController)
.build();
}
@Test
public void testAddProduct() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/product").contentType(MediaType.APPLICATION_JSON)
.content(new ObjectMapper().writeValueAsString(new Product("MS116", "Dell MS116", "Dell MS116 Usb wired optical mouse", "", 229d))))
.andReturn();
assertEquals(201, mvcResult.getResponse().getStatus());
}
@Test
public void testGetProductDetails() throws Exception {
Product product = new Product("MS116", "Dell MS116", "Dell MS116 Usb wired optical mouse", "", 229d);
when(productCatalog.get("MS116")).thenReturn(product);
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/product/{id}", "MS116").accept(MediaType.APPLICATION_JSON)).andReturn();
assertEquals(200, mvcResult.getResponse().getStatus());
Product result = new ObjectMapper().readValue(mvcResult.getResponse().getContentAsString(), Product.class);
assertEquals(product, result);
}
}