Spring Boot testy jednostkoe + @Valid nie przechodzi

0

Okej, nie wiem czy to już zmęczenie bo siedzę od rana czy co ale nie potrafię tego zrozumieć, jestem pewny na 101% że to jest jakaś pierdoła ale nie potrafię już zobaczyć swojej własnej głupoty dlatego pytam.

Mam takie POJO:

 public class AccountRegistrationRequest {

    /**
     * E-mail address that user entered during registration.
     */
    @Email
    @Size(max = 100)
    private String email;

    /**
     * Password that user entered during registration.
     */
    @NotNull
    @Size(min = 8)
    private String password;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Mam taki RestController:

@RestController
@RequestMapping("/Accounts")
 public class AccountsResource {

    AccountService accountService;
    RoleService rolesService;

    @Autowired
    public AccountsResource(AccountService accountService, RoleService rolesService) {
        this.accountService = accountService;
        this.rolesService = rolesService;
    }

    @PostMapping
    public boolean registerNewAccount(@Valid AccountRegistrationRequest accountRegReq) throws ElementAlreadyExistsException {
        try {
            RoleDTO userRole = rolesService.findByName("FREE_USER_ROLE");
            Set<RoleDTO> roles = new HashSet();
            roles.add(userRole);
            return accountService.register(accountRegReq, roles);
        } catch (ElementDoesNotExistException ex) {
            //TODO: Add Log to LOG4J file that default role does not exists in data source.
            Logger.getLogger(AccountsResource.class.getName()).log(Level.SEVERE, null, ex);
        }
        //TODO: Add Log to LOG4J file that register could not be completed for not known reaseon + parameter details.
        return false;
    }

    @PostMapping("Login")
    public AccountView login(@Valid AccountRegistrationRequest accountLoginReq) throws InvalidCredentialsException {
        return accountService.login(accountLoginReq);
    }
}

Jak widać mam na metodzie registerNewAccount @Valid.

Teraz mój test:

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

    private static final String ACCOUNTS_URL = "/Accounts";

    @MockBean
    private RoleService mockedRoleService;

    @MockBean
    private AccountService mockedAccountService;

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Before
    public void initializeMockedRoleService() throws ElementDoesNotExistException {
        RoleDTO mockedRole = new RoleDTO();
        mockedRole.setName("FREE_USER_ROLE");
        when(this.mockedRoleService.findByName("FREE_USER_ROLE")).thenReturn(mockedRole);
    }

    @Test
    public void shouldReturnErrorObjectWhenAccountWithProvidedEmailAlreadyExists() throws Exception {
        String validationErrorMessage = "Validation of input elements failed.";
        int validationErrorCode = 409;
        AccountRegistrationRequest validRegistrationReq = new AccountRegistrationRequest();
        validRegistrationReq.setEmail("**testEmaim**");
        validRegistrationReq.setPassword("TEST_CASE_PASSWORD");
        when(this.mockedAccountService.register(any(), any())).thenThrow(ElementAlreadyExistsException.class);
        
        String reqJson = objectMapper.writeValueAsString(validRegistrationReq);
        
        this.mockMvc.perform(post(ACCOUNTS_URL)
                .contentType(MediaType.APPLICATION_JSON)
                .content(reqJson))
                .andExpect(status().isConflict())
                .andExpect(jsonPath("$.errorCode").value(validationErrorCode))
                .andExpect(jsonPath("$.errorMessage").value(validationErrorMessage));
    }
}

Oraz końcowy element układanki czyli GlobalAdvice na BeanValid exceptionie:

 @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ExceptionHandler({InputValidationException.class, BindException.class})
    @ResponseBody
    public ErrorDetail handleInputValidationException() {
        String errorMessage = messageService.getLocalizedMessage("InputValidationError", getContextLanguage());
        return new ErrorDetail(HttpStatus.BAD_REQUEST.value(), errorMessage);
    }

Moje pytanie:
Dlaczego powyższy test nie wywala się na walidacji? Mimo, że model nie ma poprawnego adresu email to test przechodzi walidację i normlanie rzuca mi ten zmockowany wyjątek.

w POM.xml mam:

     <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        
        
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-java8</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
  
    </dependencies>
0

a nie musisz miec tam czasem dodatkowo @RequestBody?

czyli:

@PostMapping
    public boolean registerNewAccount(@Valid @RequestBody AccountRegistrationRequest accountRegReq) throws ElementAlreadyExistsException {
        try {
            RoleDTO userRole = rolesService.findByName("FREE_USER_ROLE");
            Set<RoleDTO> roles = new HashSet();
            roles.add(userRole);
            return accountService.register(accountRegReq, roles);
        } catch (ElementDoesNotExistException ex) {
            //TODO: Add Log to LOG4J file that default role does not exists in data source.
            Logger.getLogger(AccountsResource.class.getName()).log(Level.SEVERE, null, ex);
        }
        //TODO: Add Log to LOG4J file that register could not be completed for not known reaseon + parameter details.
        return false;
    }

Czy na pewno Spring obsługuje z paczki te adnotacje JSR 303 ?
ale chyba masz w pom.xml hibernate validatora

0

Ehhhh, moja głupota nie zna granic. Nie wiem czemu myślałem, że @RestController robi też @RequestBody na wszystkich metodach.....
Oczywiście, teraz działa poprawnie. Ogromne dzięki.

0
Zimny Ogórek napisał(a):

Ehhhh, moja głupota nie zna granic. Nie wiem czemu myślałem, że @RestController robi też @RequestBody na wszystkich metodach.....
Oczywiście, teraz działa poprawnie. Ogromne dzięki.

Spoko :) Dobrze, że to coś prostego.
Akurat takie rzeczy łatwo przeoczyć. Zwłaszcza, że sporo endpointow/controllerow powstaje przez copy-paste ;)

no i annotation mania :D

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.