Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test POST method in Spring boot using Mockito and JUnit

I am newbie to Unit testing using JUnit and Mockito in Spring boot framework. I want to test this method. How to test POST Request method:

// add Employee
@RequestMapping(method = RequestMethod.POST)
public void addEmployee(@RequestBody Employee employee){
    this.employeeService.addEmployee(employee);
}

Thank you in advance

like image 963
sk555 Avatar asked Jul 15 '18 08:07

sk555


3 Answers

Go through this following example:

@RunWith(SpringJUnit4ClassRunner.class)
public class ApplicationControllerTest {

    @Mock
    EmployeeService employeeService;

    private MockMvc mockMvc;

    @Before
    public void setUp() throws Exception {
        initMocks(this);
        YourController controller = new YourController(employeeService);
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
    }

    @Test
    public void addEmployee() throws Exception {
        Employee emp = new Employee("emp_id","emp_name");//whichever data your entity class have

        Mockito.when(employeeService.addEmployee(Mockito.any(Employee.class))).thenReturn(emp);

        mockMvc.perform(MockMvcRequestBuilders.post("/employees")
                .content(asJsonString(emp))
                .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().contentType("application/json;charset=UTF-8"));
    }

    public static String asJsonString(final Object obj) {
        try {
            return new ObjectMapper().writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

In above given example mock your service class which is required to post the data to your Employee entity class. I'm assuming that you're doing this via controller so you first need to initialize the controller which comes under the @Before annotation.

By doing above example you'll be able to post your data into the JSON format.

like image 111
Ravi Mengar Avatar answered Oct 13 '22 11:10

Ravi Mengar


  • The below example is using JUnit5, Mockito3.x, spring-boot2.4.4, and assertj3.x
  • The spring-boot-starter-test dependency from version 2.2.0 already comes with Junit 5 and contains also Hamcrest, assertj, and Mockito libraries.
  • In JUnit 5, “Runner” extension points, available in JUnit 4, are replaced by the Extension API.
  • You can register the Mockito extension via @ExtendWith.
  • Initializes mocks annotated with @Mock annotation so that explicit usage of MockitoAnnotations#initMocks(Object) is not required.
  • From spring-boot 2.1, there is no need to load the SpringExtension using annotation @ExtendWith because it's included as a meta-annotation in these annotations @DataJpaTest, @WebMvcTest, and @SpringBootTest.

Complete example with Github link: https://github.com/jdamit/DemoSpringBootApp.git

**@WebMvcTest(controllers = UserController.class)**

public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper mapper;

    @MockBean
    private UserServiceImpl userService;

    private List<UserDto> users;

    private UserDto user;

    private String URI = "/users";

    @BeforeEach
    void setUp(){
        users = List.of(new UserDto("Amit", "Kushwaha", "[email protected]", "sector 120"),
                new UserDto("Amit", "Kushwaha", "[email protected]", "sector 120"),
                new UserDto("Amit", "Kushwaha", "[email protected]", "sector 120"));
        user = new UserDto("Rahul", "Swagger", "[email protected]", "sector 120");
    }

    @Test
    //@Disabled
    void getUsersTest() throws Exception {

        Mockito.when(userService.getUsers()).thenReturn(users);

        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get(URI)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn();

        Assertions.assertThat(result).isNotNull();
        String userJson = result.getResponse().getContentAsString();
        Assertions.assertThat(userJson).isEqualToIgnoringCase(mapper.writeValueAsString(users));
    }

    @Test
    //@Disabled
    void createUserTest() throws Exception {

        Mockito.when(userService.createUser(Mockito.any(UserDto.class))).thenReturn(user);

        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post(URI)
                .contentType(MediaType.APPLICATION_JSON)
                .content(mapper.writeValueAsString(user).getBytes(StandardCharsets.UTF_8))
                .accept(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isOk())
                .andReturn();

        Assertions.assertThat(result).isNotNull();
        String userJson = result.getResponse().getContentAsString();
        Assertions.assertThat(userJson).isNotEmpty();
        Assertions.assertThat(userJson).isEqualToIgnoringCase(mapper.writeValueAsString(user));
    }
}
like image 24
Amit Kushwaha Avatar answered Oct 13 '22 11:10

Amit Kushwaha


As @merve-sahin rightly pointed out, you can use @WebMvcTest to achieve this.

Look at the following example :

@RunWith(SpringRunner.class)
@WebMvcTest(YourController.class)
public class YourControllerTest {

    @Autowired MockMvc mvc;
    @MockBean EmployeeService employeeService;

    @Test
    public void addEmployeeTest() throws Exception {

        Employee emp = createEmployee();

        mvc.perform(post("/api/employee")
            .contentType(MediaType.APPLICATION_JSON)
            .content(toJson(emp)))
            .andExpect(status().isOk());
    }
}

In Above code you can mock your dependent service using @MockBean. The test will perform post on your custom Employee object and validate the response

You can add headers, authorization while calling perform

Assuming you using JSON as media type, you can write toJson() method using any json library to convert Employee object into Json string format

private String toJson(Employee emp) {

If you are using XML, then you can do the same for XML

You can validate the response using expectations in chained way. As rightly pointed out, please checkout MockedMvc link which should help you

like image 41
Ashish Mishra Avatar answered Oct 13 '22 11:10

Ashish Mishra