1

I want to test controller of Spring boot API with class structure as below:

Controller:

@RestController
@RequestMapping("/member-management")
@Validated
public class MemberManagementController {

    private final MemberManagementService memberManagementService;

    public MemberManagementController(MemberManagementService memberManagementService) {
        this.memberManagementService = memberManagementService;
    }

    @GetMapping(value = "/view-member")
    public ResponseEntity<?> viewMember(
            @NotBlank(message = "username must not be blank!!") 
            @Size(max = 20, message = "maximum size of username id is 20!!") 
            @RequestParam("username") String username) {
        ...
    }
...

Controller advice:

@ControllerAdvice
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<Object> handleConstaintViolatoinException(final ConstraintViolationException ex) {
        List<String> details = new ArrayList<>();
        Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
        for (ConstraintViolation<?> violation : violations) {
            details.add(violation.getMessage());
        }
        ApiErrorResUtil error = new ApiErrorResUtil(String.valueOf(HttpStatus.BAD_REQUEST.value()),
                "Request param error", details);
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
...
}

Unit test:

@RunWith(MockitoJUnitRunner.class)
public class MemberManagementControllerTest {

    @InjectMocks
    private MemberManagementController memberManagementController;

    @Mock
    private MemberManagementService memberManagementService;

    private MockMvc mockMvc;

    @Before // Execute before each test method
    public void setup() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(memberManagementController)
                .setControllerAdvice(new CustomRestExceptionHandler()) // add ControllerAdvice to controller test
                .build();
    }

    @Test 
    public void viewMember_usernameSizeExceedsMaximumLimit() throws Exception {
        // Value from client
        String username = "a12345678901234567890"; // 21 characters

        MemberResDtoDataDummy memberResDtoDataDummy = new MemberResDtoDataDummy();

        when(memberManagementService.viewMember(username)).thenReturn(memberResDtoDataDummy.getMember1());

        mockMvc.perform(get("/member-management/view-member").param("username", username))
                .andExpect(status().isBadRequest()).andReturn();
    }

Problem:

java.lang.AssertionError: Status expected:<400> but was:<200>
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
    ...

Could anybody help me to resolve this proplem, why expected status is 200 instead of 400, other tests of POST, PUT, PATCH, DELETE request method with invalid inputted param are still working fine :(

1
  • 1
    Never use standaloneSetup; it fails to set up the actual context in which a controller will be operating (JSON formatting for items such as dates is the notorious failure case). Use @SpringBootTest and autowire your MockMvc. (As a side note, you're not using standard REST conventions, and I strongly recommend you do so. Name the resource, which is member, and "view" is already communicated by GET, so GET /members/{id} (if you know the ID) or GET /members?username=, which conventionally returns an array always because it's a search result.) Commented Apr 13, 2020 at 4:31

1 Answer 1

1

When you want to test your UI layer without the cost of starting a server, you have to define this test as a spring-boot one and autowired the MockMvc.

@SpringBootTest @AutoConfigureMockMvc

This class-annotations will load all the applicationContext without server.

If you just want to load your web layer, put just this annotation on your test class.

@WebMvcTest

With this annotation Spring Boot instantiates only the web layer rather than the whole context.

In both case you have to autowired the MockMvc type.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.