Public Access
test: one test container and one context per test kind
This commit is contained in:
1 parent
1f94c87a20
commit
3336181cdb
20 files changed
+65
-130
No files matched your search
@@ -1,13 +0,0 @@
|
||||
package auth_service;
|
||||
|
||||
import auth_service.shared.test.AbstractIntegrationTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AuthServiceApplicationTests extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
// If the context fails to load (e.g. Flyway migration fails or beans are missing),
|
||||
// this test will fail automatically. No explicit assertions needed.
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package auth_service.configuration.security;
|
||||
|
||||
import auth_service.shared.api.AuthCookies;
|
||||
import auth_service.shared.test.AbstractIntegrationTest;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Every access token from this context is already expired when it is issued.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
@TestPropertySource(properties = "app.auth.access-token-ttl=-1s")
|
||||
class ExpiredAccessTokenTest extends AbstractIntegrationTest {
|
||||
|
||||
private static final String EMAIL = "review-findings@example.com";
|
||||
private static final String PASSWORD = "correct horse battery";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbc;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@BeforeEach
|
||||
void seedUser() {
|
||||
jdbc.update("DELETE FROM users WHERE email = ?", EMAIL);
|
||||
jdbc.update("INSERT INTO users (email, password, enabled, steam_id) VALUES (?, ?, true, NULL)",
|
||||
EMAIL, passwordEncoder.encode(PASSWORD));
|
||||
addSettingsRows();
|
||||
}
|
||||
|
||||
private String expiredAccessCookie() throws Exception {
|
||||
Cookie cookie = mockMvc.perform(post("/api/auth/login")
|
||||
.header(ClientHeaderFilter.CLIENT_HEADER, "web")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"email\":\"" + EMAIL + "\",\"password\":\"" + PASSWORD + "\"}"))
|
||||
.andExpect(status().isOk())
|
||||
.andReturn().getResponse().getCookie(AuthCookies.ACCESS_COOKIE);
|
||||
assertNotNull(cookie);
|
||||
return cookie.getValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void expiredAccessCookie_Is401SoTheFrontendRefreshes() throws Exception {
|
||||
String expired = expiredAccessCookie();
|
||||
|
||||
mockMvc.perform(get("/api/users/me").cookie(new Cookie(AuthCookies.ACCESS_COOKIE, expired)))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package auth_service.configuration.security;
|
||||
import auth_service.shared.test.AbstractIntegrationTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.Set;
|
||||
@@ -14,7 +13,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@AutoConfigureMockMvc
|
||||
class PublicEndpointsTest extends AbstractIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -10,7 +10,6 @@ import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -27,7 +26,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
/**
|
||||
* The role markers through the real filter chain, on a probe that only this test sees.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
@Import({RoleCheckFlowTest.ProbeService.class, RoleCheckFlowTest.ProbeController.class})
|
||||
class RoleCheckFlowTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -38,7 +37,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
* The whole cookie session against a real database: login, refresh rotation, reuse detection, logout, the CSRF
|
||||
* header and CORS.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
class SessionFlowTest extends AbstractIntegrationTest {
|
||||
|
||||
private static final String EMAIL = "session-flow@example.com";
|
||||
@@ -98,6 +96,14 @@ class SessionFlowTest extends AbstractIntegrationTest {
|
||||
.andExpect(jsonPath("$.email").value(EMAIL));
|
||||
}
|
||||
|
||||
@Test
|
||||
void expiredAccessCookie_Is401SoTheFrontendRefreshes() throws Exception {
|
||||
String expired = expiredCopy(cookie(login(), AuthCookies.ACCESS_COOKIE));
|
||||
|
||||
mockMvc.perform(get("/api/users/me").cookie(new Cookie(AuthCookies.ACCESS_COOKIE, expired)))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
void noLogin_Is401() throws Exception {
|
||||
mockMvc.perform(get("/api/users/me"))
|
||||
|
||||
@@ -7,7 +7,6 @@ import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -35,7 +34,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
/**
|
||||
* "Sign in through Steam" through the whole filter chain and a real database; only Steam itself is mocked.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
class SteamLinkFlowTest extends AbstractIntegrationTest {
|
||||
|
||||
private static final String EMAIL = "steam-link@example.com";
|
||||
|
||||
@@ -10,7 +10,6 @@ import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -30,7 +29,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
* Delete my account against a real database. Core is not reachable in tests, so this also proves that a failed
|
||||
* mark in Core does not fail the delete.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
class DeletedAccountFlowTest extends AbstractIntegrationTest {
|
||||
|
||||
private static final String EMAIL = "delete-flow@example.com";
|
||||
|
||||
@@ -4,7 +4,6 @@ import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
@@ -15,7 +14,6 @@ import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@Import(AccountRepository.class)
|
||||
class AccountRepositoryTest extends AbstractPersistenceTest {
|
||||
|
||||
private static final Instant NOW = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
@@ -45,6 +43,8 @@ class AccountRepositoryTest extends AbstractPersistenceTest {
|
||||
|
||||
@BeforeEach
|
||||
void seed() {
|
||||
// Integration tests share the database and commit their rows.
|
||||
jdbc.update("DELETE FROM users");
|
||||
alice = insertUser("alice@example.com");
|
||||
bob = insertUser("bob@example.com");
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -26,7 +25,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
/**
|
||||
* Roles, "view as" and the admin users API against a real database.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
class AdminFlowTest extends AbstractIntegrationTest {
|
||||
|
||||
private static final String PASSWORD = "correct horse battery";
|
||||
|
||||
@@ -6,14 +6,12 @@ import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@Import(AdminUserRepository.class)
|
||||
class AdminUserRepositoryTest extends AbstractPersistenceTest {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -7,7 +7,6 @@ import jakarta.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
@@ -24,7 +23,6 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@AutoConfigureMockMvc
|
||||
class HintFlowTest extends AbstractIntegrationTest {
|
||||
|
||||
private static final String PASSWORD = "correct horse battery";
|
||||
|
||||
@@ -9,7 +9,6 @@ import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -19,7 +18,6 @@ import java.time.temporal.ChronoUnit;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.tuple;
|
||||
|
||||
@Import(HintRepository.class)
|
||||
class HintRepositoryTest extends AbstractPersistenceTest {
|
||||
|
||||
private static final Instant NOW = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
||||
@@ -5,7 +5,6 @@ import auth_service.shared.security.Role;
|
||||
import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -15,7 +14,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@Import(MinimalUserRepositoryImpl.class)
|
||||
class MinimalUserRepositoryTest extends AbstractPersistenceTest {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@@ -25,7 +24,6 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@AutoConfigureMockMvc
|
||||
class PublicProfileControllerTest extends AbstractIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
|
||||
+2
-4
@@ -4,7 +4,6 @@ import auth_service.modules.registration.model.Registration;
|
||||
import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@@ -15,7 +14,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@Import(RegisteredUserRepositoryImpl.class)
|
||||
class RegisteredUserRepositoryTest extends AbstractPersistenceTest {
|
||||
|
||||
@Autowired
|
||||
@@ -38,9 +36,9 @@ class RegisteredUserRepositoryTest extends AbstractPersistenceTest {
|
||||
|
||||
@Test
|
||||
void existsByDisplayName_IgnoresCase() {
|
||||
registeredUserRepository.save(registration("named@example.com", "Lobo"));
|
||||
registeredUserRepository.save(registration("named@example.com", "RegisteredName"));
|
||||
|
||||
assertTrue(registeredUserRepository.existsByDisplayName("lobo"));
|
||||
assertTrue(registeredUserRepository.existsByDisplayName("registeredname"));
|
||||
assertFalse(registeredUserRepository.existsByDisplayName("Wolf"));
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import auth_service.shared.test.AbstractPersistenceTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.jpa.test.autoconfigure.TestEntityManager;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -21,7 +20,6 @@ import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@Import(UserRepositoryImpl.class)
|
||||
class UserRepositoryTest extends AbstractPersistenceTest {
|
||||
|
||||
@Autowired
|
||||
@@ -224,13 +222,13 @@ class UserRepositoryTest extends AbstractPersistenceTest {
|
||||
var settings = UserSettings.builder().language("en").theme("light").build();
|
||||
|
||||
// Act
|
||||
updateSettings(owner.getId(), "Lobo", settings);
|
||||
updateSettings(owner.getId(), "RepoName", settings);
|
||||
entityManager.flush();
|
||||
|
||||
// Assert
|
||||
assertEquals("Lobo", findByEmail("owner2@example.com").orElseThrow().getDisplayName());
|
||||
assertFalse(userRepository.isDisplayNameUsedByOtherUser(owner.getId(), "lobo"));
|
||||
assertTrue(userRepository.isDisplayNameUsedByOtherUser(other.getId(), "LOBO"));
|
||||
assertEquals("RepoName", findByEmail("owner2@example.com").orElseThrow().getDisplayName());
|
||||
assertFalse(userRepository.isDisplayNameUsedByOtherUser(owner.getId(), "reponame"));
|
||||
assertTrue(userRepository.isDisplayNameUsedByOtherUser(other.getId(), "REPONAME"));
|
||||
assertFalse(userRepository.isDisplayNameUsedByOtherUser(other.getId(), "Wolf"));
|
||||
}
|
||||
|
||||
@@ -243,7 +241,7 @@ class UserRepositoryTest extends AbstractPersistenceTest {
|
||||
.registrationDate(LocalDateTime.now())
|
||||
.build());
|
||||
|
||||
updateSettings(userEntity.getId(), "Lobo",
|
||||
updateSettings(userEntity.getId(), "RepoName",
|
||||
UserSettings.builder().language("de").theme("dark").publicProfile(true).build());
|
||||
entityManager.flush();
|
||||
entityManager.clear();
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package auth_service.shared.test;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jws;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
@@ -13,25 +17,21 @@ import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Base class for integration tests.
|
||||
* Full Spring context with Testcontainers.
|
||||
*/
|
||||
@Tag("IntegrationTest")
|
||||
@AutoConfigureMockMvc
|
||||
// The account cleanup must not run by itself, and Core is never reachable in tests.
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {"app.account-cleanup.cron=-", "app.core.internal-url=http://127.0.0.1:1"})
|
||||
public abstract class AbstractIntegrationTest {
|
||||
|
||||
// One container per JVM, not per class: Spring caches the context across test classes,
|
||||
// and a per-class container would be stopped under the cached context.
|
||||
@ServiceConnection
|
||||
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17-alpine");
|
||||
|
||||
static {
|
||||
postgres.start();
|
||||
}
|
||||
static PostgreSQLContainer<?> postgres = TestPostgres.CONTAINER;
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate baseJdbc;
|
||||
@@ -54,6 +54,19 @@ public abstract class AbstractIntegrationTest {
|
||||
registry.add("auth.registration.invitation-code", () -> "test-invite-code");
|
||||
}
|
||||
|
||||
/**
|
||||
* The same token, signed again with an expiry in the past.
|
||||
*/
|
||||
protected static String expiredCopy(String token) {
|
||||
Jws<Claims> jws = Jwts.parser().verifyWith(KEYS.getPublic()).build().parseSignedClaims(token);
|
||||
return Jwts.builder()
|
||||
.header().keyId(jws.getHeader().getKeyId()).and()
|
||||
.claims(jws.getPayload())
|
||||
.expiration(new Date(System.currentTimeMillis() - 1000))
|
||||
.signWith(KEYS.getPrivate(), Jwts.SIG.EdDSA)
|
||||
.compact();
|
||||
}
|
||||
|
||||
private static KeyPair generateKeys() {
|
||||
try {
|
||||
return KeyPairGenerator.getInstance("Ed25519").generateKeyPair();
|
||||
|
||||
@@ -4,6 +4,9 @@ import org.junit.jupiter.api.Tag;
|
||||
import org.springframework.boot.data.jpa.test.autoconfigure.DataJpaTest;
|
||||
import org.springframework.boot.jdbc.test.autoconfigure.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
/**
|
||||
@@ -11,16 +14,11 @@ import org.testcontainers.containers.PostgreSQLContainer;
|
||||
* Slices only the persistence layer with Testcontainers.
|
||||
*/
|
||||
@Tag("PersistenceTest")
|
||||
@DataJpaTest
|
||||
// Every @Repository, so all persistence tests share one Spring context.
|
||||
@DataJpaTest(includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Repository.class))
|
||||
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
|
||||
public abstract class AbstractPersistenceTest {
|
||||
|
||||
// One container per JVM, not per class: Spring caches the context across test classes,
|
||||
// and a per-class container would be stopped under the cached context.
|
||||
@ServiceConnection
|
||||
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17-alpine");
|
||||
|
||||
static {
|
||||
postgres.start();
|
||||
}
|
||||
static PostgreSQLContainer<?> postgres = TestPostgres.CONTAINER;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package auth_service.shared.test;
|
||||
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
/**
|
||||
* One database for all integration and persistence tests of a JVM. Integration tests commit their rows, so every
|
||||
* test uses emails and display names no other test uses.
|
||||
*/
|
||||
final class TestPostgres {
|
||||
|
||||
static final PostgreSQLContainer<?> CONTAINER = new PostgreSQLContainer<>("postgres:17-alpine");
|
||||
|
||||
static {
|
||||
CONTAINER.start();
|
||||
}
|
||||
|
||||
private TestPostgres() {
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user