Testing the Web Layer/Controllers: -
To do this we will use annotations:
@WebMvcTest
@MockBean
Object:
MockMvc
Testing Controllers-with @WebMvcTest: -
Controller is dependent on Service Layer, if Service layer is not yet implemented, we can still test it by Mocking Service Layer.
• For our project, Customer microservice create a class called 'CustomerControllerTest' and annotate it with the below
– @RunWith(SpringRunner.class) : Helps in configuring Spring application context
– @WebMvcTest(CustomerController.class): Use this annotation for unit testing of MVC based application. Helps in configuring MVC infrastructure for testing without a
need for HTTP Servers.
Project Set-up:
– Add Maven dependencies to your Spring Boot project
• spring-boot-starter-test
• Database which is needed only while testing
Autowire MockMvc and Mock the beans needed in application context.
@WebMvcTest auto-configures MockMvc which offers a powerful way of easy testing MVC controllers without starting full HTTP server.
@Autowired
private MockMvc
@MockBean
private CustomerService service;
We also need the DTO’s and entity bean needed.
static CustomerDTO custDTO;
static Customer cust;
• Initialize the values for the variables.
– If initialization has to be done only once, do it in a public static method annotated using @BeforeClass
– If initialization needs to be done after every test method is executed then do it in a public void method annotated using @Before as shown below
@BeforeClass
public static void initialise() {
custDTO = new CustomerDTO();cust = new Customer();
}
@Before
public void init() {
MockitoAnnotations.initMocks(this);custDTO.setSsnId("123456789010");custDTO.setAddress("#25, Millers Road, Bangalore");custDTO.setDob("20-Mar-1981");custDTO.setEmailId("Robert_Smith@gmail.com");custDTO.setFirstName("Robert");custDTO.setLastName("Smith");cust = CustomerDTO.prepareEntity(custDTO);
}
Let us write the test case for the below user story which fetches the customer details whose phoneNo will be sent as path variable.
/customers/{phoneNo}
• Before we write the test let us set how our service layer should behave as we are not going to test against the actual service layer
String phoneNo = "9876536750";
custDTO.setPhoneNo("9876536750");
//Training the custService Mock object how to respond
when(custService.getCustomerDetails(phoneNo)).thenReturn(custDTO);
- Now let us make a call to our controller using mockMvc object
mockMvc.perform(get("/customers/" + phoneNo)).andExpect(status().isOk())
.andExpect(jsonPath("$.ssnId", is(custDTO.getSsnId())))
.andExpect(jsonPath("$.address", is(custDTO.getAddress())))
.andExpect(jsonPath("$.dob", is(custDTO.getDob())))
.andExpect(jsonPath("$.emailId", is(custDTO.getEmailId())))
.andExpect(jsonPath("$.firstName", is(custDTO.getFirstName())))
.andExpect(jsonPath("$.lastName", is(custDTO.getLastName())))
.andExpect(jsonPath("$.phoneNo", is(custDTO.getPhoneNo())));
verify(custService).getCustomerDetails(phoneNo);
– In the above code we are asking mockMvc to perform a get call to customers/{phoneNo} url and
expect the status as OK and also expect a jsonResponse whose values we are verifying against a
pre-defined object
– Replace get with the appropriate HTTP method name (in lowercase) if the call is via HTTP
PUT/POST/DELETE/