Skip to content

Commit 2be237f

Browse files
committed
Add test container, add sample integration test case, upgrade jaccoo library version
1 parent 786bfc0 commit 2be237f

File tree

9 files changed

+2592
-7
lines changed

9 files changed

+2592
-7
lines changed

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ openApiVersion=2.1.0
66
commonsDaoVersion=0.0.11
77
jacksonVersion=2.15.3
88
#Test property
9-
jacocoVersion=0.8.8
10-
testContainerVersion=1.16.2
9+
jacocoVersion=0.8.11
10+
testContainerVersion=1.19.5
1111
keycloakTestContainerVersion=1.9.0
1212
keycloakAdminClientVersion=16.1.1
1313
liquibaseVersion=4.25.0

ss-web/src/main/java/ss/mod/demo/web/config/security/AuthenticationConfig.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
99
import org.springframework.context.annotation.Bean;
1010
import org.springframework.context.annotation.Configuration;
11-
import org.springframework.data.domain.AuditorAware;
1211
import org.springframework.http.HttpMethod;
1312
import org.springframework.security.config.Customizer;
1413
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@@ -24,7 +23,6 @@
2423
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
2524
import ss.mod.demo.api.constant.ContURI;
2625
import ss.mod.demo.api.constant.ContValue;
27-
import ss.mod.demo.service.entity.AuditorAwareImpl;
2826

2927
import java.util.List;
3028

@@ -63,8 +61,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
6361
auth.requestMatchers(new AntPathRequestMatcher(ContURI.CONTEXT_SWAGGER_IU_ALL)).permitAll();
6462
auth.requestMatchers(new AntPathRequestMatcher(ContURI.CONTEXT_HEALTH_ALL)).permitAll();
6563
auth.requestMatchers(new AntPathRequestMatcher(ContURI.CONTEXT_PRIVATE_ALL)).permitAll();
66-
auth.requestMatchers(new AntPathRequestMatcher(ContURI.CONTEXT_AUTHENTICATED_ALL)).hasRole("<UserRole>");
67-
auth.requestMatchers(new AntPathRequestMatcher(ContURI.CONTEXT_AUTHENTICATED_WITH_NO_FILTER_ALL)).hasRole("<UserRole>");
64+
auth.requestMatchers(new AntPathRequestMatcher(ContURI.CONTEXT_AUTHENTICATED_ALL)).hasRole("SWD_ADMIN");
65+
auth.requestMatchers(new AntPathRequestMatcher(ContURI.CONTEXT_AUTHENTICATED_WITH_NO_FILTER_ALL)).hasRole("SWD_ADMIN");
6866
}).oauth2ResourceServer(oath -> oath.jwt(jwt -> jwt.jwtAuthenticationConverter(new CustomAuthenticationConverter(configProperties.roleClientId()))));
6967
return http.build();
7068
}
@@ -78,7 +76,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
7876
*/
7977
@Bean
8078
@ConditionalOnProperty(value = "app.security.enabled", havingValue = "false")
81-
public WebSecurityCustomizer securityCustomizer() {
79+
public static WebSecurityCustomizer securityCustomizer() {
8280
AuthenticationConfig.log.warn("Disable security : This is not recommended to use in production environments.");
8381
return web -> web.ignoring().requestMatchers(new AntPathRequestMatcher("**"));
8482
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package ss.mod.demo.util;
2+
3+
import dasniko.testcontainers.keycloak.KeycloakContainer;
4+
import org.keycloak.admin.client.KeycloakBuilder;
5+
import org.springframework.boot.test.util.TestPropertyValues;
6+
import org.springframework.context.ApplicationContextInitializer;
7+
import org.springframework.context.ConfigurableApplicationContext;
8+
import org.testcontainers.containers.PostgreSQLContainer;
9+
10+
import java.time.Duration;
11+
import java.time.temporal.ChronoUnit;
12+
13+
import static ss.mod.demo.util.constant.KeycloakTestConstant.BEARER;
14+
import static ss.mod.demo.util.constant.KeycloakTestConstant.INVALID_USER_NAME;
15+
import static ss.mod.demo.util.constant.KeycloakTestConstant.KEYCLOAK_ADMIN_USERNAME;
16+
import static ss.mod.demo.util.constant.KeycloakTestConstant.KEYCLOAK_PRIVATE_CLIENT;
17+
import static ss.mod.demo.util.constant.KeycloakTestConstant.KEYCLOAK_PUBLIC_CLIENT;
18+
import static ss.mod.demo.util.constant.KeycloakTestConstant.KEYCLOAK_REALM;
19+
import static ss.mod.demo.util.constant.KeycloakTestConstant.PASSWORD;
20+
import static ss.mod.demo.util.constant.KeycloakTestConstant.REAL_FILE_PATH;
21+
import static ss.mod.demo.util.constant.KeycloakTestConstant.VALID_USER_NAME;
22+
23+
24+
public class ContainerContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
25+
26+
27+
private static final PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:15.2");
28+
private static final KeycloakContainer keycloak = new KeycloakContainer("jboss/keycloak:16.1.1")
29+
.withRealmImportFile(REAL_FILE_PATH)
30+
.withAdminPassword(KEYCLOAK_ADMIN_USERNAME)
31+
.withAdminPassword(PASSWORD);
32+
33+
static String createToken(boolean validUser) {
34+
35+
KeycloakBuilder keycloakBuilder = KeycloakBuilder.builder()
36+
.serverUrl(ContainerContextInitializer.keycloak.getAuthServerUrl())
37+
.realm(KEYCLOAK_REALM)
38+
.clientId(KEYCLOAK_PUBLIC_CLIENT)
39+
.username(INVALID_USER_NAME)
40+
.password(PASSWORD);
41+
if (validUser) {
42+
keycloakBuilder.username(VALID_USER_NAME);
43+
}
44+
String access_token = keycloakBuilder.build().tokenManager().getAccessToken().getToken();
45+
return BEARER + access_token;
46+
}
47+
48+
@Override
49+
public void initialize(ConfigurableApplicationContext applicationContext) {
50+
ContainerContextInitializer.postgreSQLContainer.start();
51+
TestPropertyValues testPropertyValues = TestPropertyValues.of(
52+
"spring.datasource.url=" + ContainerContextInitializer.postgreSQLContainer.getJdbcUrl() + "&currentSchema=public",
53+
"spring.datasource.username=" + ContainerContextInitializer.postgreSQLContainer.getUsername(),
54+
"spring.datasource.password=" + ContainerContextInitializer.postgreSQLContainer.getPassword()
55+
);
56+
57+
boolean keycloakContainer = Boolean.valueOf(applicationContext.getEnvironment().getProperty("app.container.keycloak"));
58+
if (keycloakContainer) {
59+
ContainerContextInitializer.keycloak.withStartupTimeout(Duration.of(5, ChronoUnit.MINUTES));
60+
ContainerContextInitializer.keycloak.start();
61+
62+
testPropertyValues = testPropertyValues.and("app.security.auth-server-url=" + ContainerContextInitializer.keycloak.getAuthServerUrl(),
63+
"app.security.realm=" + KEYCLOAK_REALM,
64+
"app.security.clientId=" + KEYCLOAK_PRIVATE_CLIENT);
65+
}
66+
testPropertyValues.applyTo(applicationContext.getEnvironment());
67+
}
68+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package ss.mod.demo.util;
2+
3+
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.core.env.Environment;
6+
import org.springframework.http.HttpHeaders;
7+
import org.springframework.stereotype.Component;
8+
import org.springframework.util.LinkedMultiValueMap;
9+
import org.springframework.util.MultiValueMap;
10+
11+
@Component
12+
public class TestHelper {
13+
14+
private static Environment env;
15+
16+
@Autowired
17+
public TestHelper(Environment environment) {
18+
TestHelper.env = environment;
19+
}
20+
21+
public static MultiValueMap<String, String> prepareHeader(boolean validUser) {
22+
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
23+
if (Boolean.parseBoolean(TestHelper.env.getProperty("app.security.enabled"))) {
24+
headers.add(HttpHeaders.AUTHORIZATION, ContainerContextInitializer.createToken(validUser));
25+
}
26+
return headers;
27+
}
28+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package ss.mod.demo.util.constant;
2+
3+
public class KeycloakTestConstant {
4+
public static final String BEARER = "Bearer ";
5+
public static final String REAL_FILE_PATH = "app-test-realm.json";
6+
public static final String KEYCLOAK_ADMIN_USERNAME = "admin";
7+
public static final String KEYCLOAK_REALM = "SWD";
8+
public static final String KEYCLOAK_PUBLIC_CLIENT = "pb_backend";
9+
public static final String KEYCLOAK_PRIVATE_CLIENT = "pv_backend";
10+
public static final String VALID_USER_NAME = "valid-user";
11+
public static final String INVALID_USER_NAME = "invalid-user";
12+
public static final String PASSWORD = "password"; //pragma: allowlist secret
13+
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package ss.mod.demo.util.constant;
2+
3+
public class TestConstant {
4+
5+
public static final String TEST_USER_NAME = "username1";
6+
public static final int TEST_USER_AGE = 20;
7+
public static final String TEST_USER_CITY = "testcity";
8+
public static final String TEST_USER_COUNTRY = "testcountry";
9+
10+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package ss.mod.demo.util.constant;
2+
3+
import lombok.AccessLevel;
4+
import lombok.NoArgsConstructor;
5+
import ss.mod.demo.api.model.request.UserRequest;
6+
7+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
8+
public final class TestDataUtil {
9+
10+
11+
public static UserRequest getUserRequest() {
12+
return new UserRequest(TestConstant.TEST_USER_NAME, TestConstant.TEST_USER_AGE, TestConstant.TEST_USER_CITY, TestConstant.TEST_USER_COUNTRY);
13+
}
14+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package ss.mod.demo.web;
2+
3+
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import org.junit.jupiter.api.Assertions;
6+
import org.junit.jupiter.api.BeforeAll;
7+
import org.junit.jupiter.api.BeforeEach;
8+
import org.junit.jupiter.api.Test;
9+
import org.junit.jupiter.api.TestInstance;
10+
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.boot.test.context.SpringBootTest;
12+
import org.springframework.boot.test.web.client.TestRestTemplate;
13+
import org.springframework.core.ParameterizedTypeReference;
14+
import org.springframework.http.HttpEntity;
15+
import org.springframework.http.HttpMethod;
16+
import org.springframework.http.ResponseEntity;
17+
import org.springframework.test.context.ActiveProfiles;
18+
import org.springframework.test.context.ContextConfiguration;
19+
import org.springframework.test.context.transaction.BeforeTransaction;
20+
import ss.mod.demo.SWMainApplication;
21+
import ss.mod.demo.api.constant.ContURI;
22+
import ss.mod.demo.api.model.request.UserRequest;
23+
import ss.mod.demo.api.model.response.ResponseBody;
24+
import ss.mod.demo.api.model.response.UserResponse;
25+
import ss.mod.demo.dao.repository.UserMasterRepository;
26+
import ss.mod.demo.util.ContainerContextInitializer;
27+
import ss.mod.demo.util.TestHelper;
28+
import ss.mod.demo.util.constant.TestDataUtil;
29+
30+
31+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { SWMainApplication.class })
32+
@ActiveProfiles("test")
33+
@ContextConfiguration(initializers = { ContainerContextInitializer.class })
34+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
35+
class UserManagementResourceTest {
36+
37+
38+
@Autowired
39+
UserMasterRepository userMasterRepository;
40+
@Autowired
41+
private TestRestTemplate restTemplate;
42+
@Autowired
43+
private ObjectMapper mapper;
44+
45+
46+
@BeforeAll
47+
public final void onlyOnce() {
48+
49+
}
50+
51+
/**
52+
* This method execute before every test method execute and before any transaction in database happen and create company.
53+
*/
54+
@BeforeEach
55+
@BeforeTransaction
56+
public final void before() {
57+
userMasterRepository.deleteAll();
58+
}
59+
60+
@Test
61+
void createUser_200() {
62+
ResponseEntity<ResponseBody<UserResponse>> responseEntity = this.createUser(TestDataUtil.getUserRequest());
63+
Assertions.assertNotNull(responseEntity);
64+
Assertions.assertTrue(responseEntity.getStatusCode().is2xxSuccessful());
65+
Assertions.assertNotNull(responseEntity.getBody());
66+
Assertions.assertNotNull(responseEntity.getBody().getBody());
67+
Assertions.assertNotNull(responseEntity.getBody().getBody().id());
68+
}
69+
70+
71+
private ResponseEntity<ResponseBody<UserResponse>> createUser(UserRequest userRequest) {
72+
return restTemplate.exchange(ContURI.USER, HttpMethod.POST, new HttpEntity<>(userRequest, TestHelper.prepareHeader(true)),
73+
new ParameterizedTypeReference<>() {
74+
});
75+
}
76+
77+
}

0 commit comments

Comments
 (0)