42. Test custom exception handling (#3)
This commit is contained in:
@ -1,10 +1,10 @@
|
|||||||
package net.shyshkin.study.fullstack.supportportal.backend.config;
|
package net.shyshkin.study.fullstack.supportportal.backend.config;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.shyshkin.study.fullstack.supportportal.backend.constant.SecurityConstants;
|
|
||||||
import net.shyshkin.study.fullstack.supportportal.backend.filter.JwtAccessDeniedHandler;
|
import net.shyshkin.study.fullstack.supportportal.backend.filter.JwtAccessDeniedHandler;
|
||||||
import net.shyshkin.study.fullstack.supportportal.backend.filter.JwtAuthenticationEntryPoint;
|
import net.shyshkin.study.fullstack.supportportal.backend.filter.JwtAuthenticationEntryPoint;
|
||||||
import net.shyshkin.study.fullstack.supportportal.backend.filter.JwtAuthorizationFilter;
|
import net.shyshkin.study.fullstack.supportportal.backend.filter.JwtAuthorizationFilter;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
@ -34,6 +34,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
|
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
|
||||||
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
||||||
|
|
||||||
|
@Value("${app.public-urls}")
|
||||||
|
private String[] publicUrls;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
@ -44,7 +47,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||||
|
|
||||||
http.authorizeRequests()
|
http.authorizeRequests()
|
||||||
.antMatchers(SecurityConstants.PUBLIC_URLS).permitAll()
|
.antMatchers(publicUrls).permitAll()
|
||||||
.anyRequest().authenticated();
|
.anyRequest().authenticated();
|
||||||
|
|
||||||
http.exceptionHandling()
|
http.exceptionHandling()
|
||||||
|
|||||||
@ -11,5 +11,4 @@ public class SecurityConstants {
|
|||||||
public static final String FORBIDDEN_MESSAGE = "You need to log in to access this page";
|
public static final String FORBIDDEN_MESSAGE = "You need to log in to access this page";
|
||||||
public static final String ACCESS_DENIED_MESSAGE = "You do not have permission to access this page";
|
public static final String ACCESS_DENIED_MESSAGE = "You do not have permission to access this page";
|
||||||
public static final String OPTIONS_HTTP_METHOD = "OPTIONS";
|
public static final String OPTIONS_HTTP_METHOD = "OPTIONS";
|
||||||
public static final String[] PUBLIC_URLS = { "/user/login", "/user/register", "/user/image/**" };
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ spring:
|
|||||||
hibernate:
|
hibernate:
|
||||||
dialect: org.hibernate.dialect.MySQL8Dialect
|
dialect: org.hibernate.dialect.MySQL8Dialect
|
||||||
app:
|
app:
|
||||||
|
public-urls: /user/login,/user/register,/user/image/**
|
||||||
jwt:
|
jwt:
|
||||||
secret: VeRy_5ecretP@55W0rd!
|
secret: VeRy_5ecretP@55W0rd!
|
||||||
# secret: ${random.value} #Does not work - every time generates new value
|
# secret: ${random.value} #Does not work - every time generates new value
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package net.shyshkin.study.fullstack.supportportal.backend.controller;
|
||||||
|
|
||||||
|
import net.shyshkin.study.fullstack.supportportal.backend.exception.domain.EmailExistsException;
|
||||||
|
import net.shyshkin.study.fullstack.supportportal.backend.exception.domain.UserNotFoundException;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/exceptions")
|
||||||
|
public class ExceptionsController {
|
||||||
|
|
||||||
|
@GetMapping("/emailExists")
|
||||||
|
public String emailExistsException() throws EmailExistsException {
|
||||||
|
throw new EmailExistsException("This email is already taken");
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/userNotFound")
|
||||||
|
public String userNotFoundException() throws UserNotFoundException {
|
||||||
|
throw new UserNotFoundException("The user was not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
package net.shyshkin.study.fullstack.supportportal.backend.controller;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.shyshkin.study.fullstack.supportportal.backend.domain.HttpResponse;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
import org.springframework.test.context.TestPropertySource;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.within;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
|
@TestPropertySource(properties = {
|
||||||
|
"app.public-urls=**"
|
||||||
|
})
|
||||||
|
@ActiveProfiles("local")
|
||||||
|
class ExceptionsControllerTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
TestRestTemplate restTemplate;
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({
|
||||||
|
"emailExists,THIS EMAIL IS ALREADY TAKEN",
|
||||||
|
"userNotFound,THE USER WAS NOT FOUND"
|
||||||
|
})
|
||||||
|
void badRequestException(String endpoint, String expectedMessage) {
|
||||||
|
|
||||||
|
//when
|
||||||
|
var responseEntity = restTemplate.getForEntity("/exceptions/{endpoint}", HttpResponse.class, endpoint);
|
||||||
|
|
||||||
|
//then
|
||||||
|
log.debug("Response entity: {}", responseEntity);
|
||||||
|
assertThat(responseEntity.getStatusCode()).isEqualTo(BAD_REQUEST);
|
||||||
|
assertThat(responseEntity.getBody())
|
||||||
|
.isNotNull()
|
||||||
|
.hasNoNullFieldsOrProperties()
|
||||||
|
.satisfies(httpResponse -> assertAll(
|
||||||
|
() -> assertThat(httpResponse.getHttpStatus()).isEqualTo(BAD_REQUEST),
|
||||||
|
() -> assertThat(httpResponse.getHttpStatusCode()).isEqualTo(BAD_REQUEST.value()),
|
||||||
|
() -> assertThat(httpResponse.getMessage()).isEqualTo(expectedMessage),
|
||||||
|
() -> assertThat(httpResponse.getReason()).isEqualTo(BAD_REQUEST.getReasonPhrase().toUpperCase()),
|
||||||
|
() -> assertThat(httpResponse.getTimestamp()).isCloseTo(LocalDateTime.now(), within(200, ChronoUnit.MILLIS))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user