lundi 26 octobre 2020

How to test an insert with MockMvc? Assert expecting 201, but I get 409

I am pretty new at tests written for MVC apps, and I am trying to create a simple test for inserting an user in the database.

I am making use of the following classes:

DTO - UserSavingDTO

public class UserSavingDTO {
    private String name;

    private String dateOfBirth;

    private String gender;

    private String address;

    private String username;

    private String password;

    public UserSavingDTO() {

    }

    public UserSavingDTO(String name, String dateOfBirth, String gender, String address, String username, String password) {
        this.name = name;
        this.dateOfBirth = dateOfBirth;
        this.gender = gender;
        this.address = address;
        this.username = username;
        this.password = password;
    }
}

Service - UserService

@Service
@Transactional
public class UserService {
    @Autowired
    EntityManager em;

    @Autowired
    UserRepository userRepository;

    @Autowired
    RoleRepository roleRepository;

    @Autowired
    DoctorRepository doctorRepository;

    public Doctor saveDoctor(UserSavingDTO userSavingDTO) throws ParseException {

        Role role = new Role();

        /*role.setName("ROLE_PATIENT");

        roleRepo.save(role);*/

        role = roleRepository.findByName("ROLE_DOCTOR");

        Collection<Role> roleCollection = new ArrayList<Role>();

        roleCollection.add(role);

        Doctor doctor = new Doctor();

        doctor.setId(UUID.randomUUID().toString());
        doctor.setName(userSavingDTO.getName());
        doctor.setDateOfBirth(DateUtils.getPrettyDateStringForSQLDate(userSavingDTO.getDateOfBirth()));
        doctor.setGender(userSavingDTO.getGender());
        doctor.setAddress(userSavingDTO.getAddress());
        doctor.setUsername(userSavingDTO.getUsername());
        doctor.setPassword(userSavingDTO.getGender());
        doctor.setRoles(roleCollection);

        return doctorRepository.save(doctor);
    }
}

Controller - RegistrationController

@RestController
@CrossOrigin
@RequestMapping("/register")
public class RegistrationController {
    @Autowired
    UserService userService;

    ResponseFactory responseFactory = new ResponseFactory();

    //CREATE DOCTOR
    @PostMapping
    public ResponseEntity createDoctor(@RequestBody UserSavingDTO userSavingDTO) throws ParseException {

        Response response = responseFactory.getResponseMessage(ResponseEnum.ResponseCreate);

        if (UserValidator.validateUsername(userSavingDTO.getUsername())) {
            if(!(UserValidator.existsByUsername(userSavingDTO.getUsername(), userService))) {
                if (UserValidator.validatePassword(userSavingDTO.getPassword())) {
                    Doctor doctor = userService.saveDoctor(userSavingDTO);

                    if (doctor != null) {
                        return response.responseMessage("User is successfully created!", SeverityEnum.INFORMATION_MESSAGE.toString(), HttpStatus.CREATED);
                    } else
                        return response.responseMessage("Troubles saving it into the database!", SeverityEnum.WARNING_MESSAGE.toString(), HttpStatus.CONFLICT);
                } else
                    return response.responseMessage("Wrong password format!", SeverityEnum.WARNING_MESSAGE.toString(), HttpStatus.NOT_IMPLEMENTED);
            } else
                return response.responseMessage("The doctor with the specified username already exists!", SeverityEnum.ERROR_MESSAGE.toString(), HttpStatus.NOT_IMPLEMENTED);
        } else
            return response.responseMessage("You must specify an username!", SeverityEnum.WARNING_MESSAGE.toString(), HttpStatus.NOT_IMPLEMENTED);
    }
}

Run

@SpringBootApplication
@Validated
public class Run extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Run.class);
    }

    public static void main(String[] args) {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
        SpringApplication.run(Run.class, args);
    }
}

Test - UserControllerUnitTest

public class UserControllerUnitTest extends RunTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService service;

    @Test
    public void insertDoctorTest() throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        UserSavingDTO doctorDTO = new UserSavingDTO("Test Name", "26/10/2020", "Test Gender", "Test Address", "Test Username", "test");

        mockMvc.perform(post("/register")
                .content(objectMapper.writeValueAsString(doctorDTO))
                .contentType("application/json"))
                .andExpect(status().isOk());
    }
}

Test - RunTest

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Run.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(locations = "classpath:application-test.properties")
@AutoConfigureMockMvc
public class RunTest {
    @Test
    public void contextLoads() {
        assert true ;
    }
}

While I am running the request in Postman everything works accordingly, as expected: Postman

While I am running the provided test it fails with the code 409:

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /register
       Parameters = {}
          Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"140"]
             Body = {"name":"Test Name","dateOfBirth":"26/10/2020","gender":"Test Gender","address":"Test Address","username":"Test Username","password":"test"}
    Session Attrs = {}

Handler:
             Type = ro.tuc.ds2020.controllers.RegistrationController
           Method = ro.tuc.ds2020.controllers.RegistrationController#createDoctor(UserSavingDTO)

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 409
    Error message = null
          Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", Content-Type:"application/json"]
     Content type = application/json
             Body = {"message":"Troubles saving it into the database!","optionPaneType":"WARNING_MESSAGE"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

java.lang.AssertionError: Status 
Expected :200
Actual   :409

I cannot pinpoint what am I doing different than the Postman test. Why do I get a response in the test that I am having trouble saving it in the database meaning that doctor is null, while I am entering the same values for attributes in Postman and I do not get a null value for doctor?

Aucun commentaire:

Enregistrer un commentaire