Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot returning wrong Status Code only in Unit Test

I'm developing a REST API with Spring Boot.

I have a controller to create a new user, that responds with 201 (CREATED) when the user is created. The response has no body content.

Using Postman, or any browser, I got a 201 response. But when I try with unit test (Mockito), the response is 200.

Here is my code:

Controller:

public CompletableFuture<ResponseEntity<Void>> registerNewUser(
    @RequestBody @Valid RegisterUserDto newUser
) throws ExecutionException, InterruptedException {

  // user service return a completable future void 
  return userService.registerNewUser(newUser).thenApply(u -> new ResponseEntity<>(u, HttpStatus.CREATED));
}

The user service returns a completable future void when the register process is completed.

@Async
CompletableFuture<Void> registerNewUser(NewUserDto newUserDto) throws ExecutionException, InterruptedException;

Then, in my unit test, I have the following code:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class UsersControllerTest {

  @Autowired
  private MockMvc mvc;

  @Mock
  private UsersService userService;

  @InjectMocks
  private UsersControllers usersController;

  @Before
  public void init() {
    MockitoAnnotations.initMocks(this);
    this.mvc = MockMvcBuilders.standaloneSetup(usersController).build();
  }

  @Test
  public void mustCreateANewUser() throws Exception {
    NewUserDto userMock = new NewUserDto("firstname", "lastname", "login", "password");

    when(userService.registerNewUser(any(NewUserDto.class)))
      .thenReturn(CompletableFuture.completedFuture(null));

    mvc.perform(post("/api/users/new")
                    .content(TestHelpers.convertToJson(userMock))
                    .contentType(TestHelpers.getJsonMediaType()))
        .andExpect(status().isCreated());
  }
}

TestHelpers.convertToJson and TestHelpers.getJsonMediaType are static methods.

public static MediaType getJsonMediaType() {
  return new MediaType(MediaType.APPLICATION_JSON.getType(),
                       MediaType.APPLICATION_JSON.getSubtype(),
                       Charset.forName("utf8"));
}

public static String convertToJson(Object o) throws IOException {
  ObjectMapper mapper = new ObjectMapper();
  return mapper.writeValueAsString(o);
}

I do not understand why the response code was 200 on unit test. In any part of my controller, service, or controller advice I have a response 200 OK.

like image 874
Roberto Correia Avatar asked Oct 24 '17 11:10

Roberto Correia


1 Answers

The problem was because my controller and service are async, so my unit test it's not waiting for the correct response.

Changed my unit test to:

MvcResult result = mvc.perform(post("/api/users/new")
  .content(TestHelpers.convertToJson(registroMock))
  .contentType(TestHelpers.getJsonMediaType()))
  .andReturn();

mvc.perform(asyncDispatch(result))
   .andExpect(status().isCreated());
like image 58
Roberto Correia Avatar answered Nov 01 '22 00:11

Roberto Correia