Added new tests fixed some problem

This commit is contained in:
lobo committed 2026-04-18 11:28:06 +02:00
1 parent 14a4ccfb87
commit 20402eb7c4
32 files changed
+11120 -78

No files matched your search

@@ -1,25 +1,9 @@
package auth_service;
import auth_service.shared.test.AbstractIntegrationTest;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@SpringBootTest
@Testcontainers
class AuthServiceApplicationTests {
/**
* Define the PostgreSQL container.
*
* @ServiceConnection automatically configures the application properties
* (URL, username, password) for this specific container.
*/
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17.9");
class AuthServiceApplicationTests extends AbstractIntegrationTest {
@Test
void contextLoads() {
@@ -1,5 +1,6 @@
package auth_service.architecture;
import auth_service.shared.test.AbstractArchitectureTest;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
@@ -14,7 +15,7 @@ import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
* Analyzes all classes in the 'auth_service' package, ignoring test classes.
*/
@AnalyzeClasses(packages = "auth_service", importOptions = ImportOption.DoNotIncludeTests.class)
class ArchitectureTest {
class ArchitectureTest extends AbstractArchitectureTest {
// ===================================================================================
// 1. DOMAIN INDEPENDENCE (Slices)
@@ -75,6 +76,24 @@ class ArchitectureTest {
.should().dependOnClassesThat().resideInAPackage("..persistence..")
.because("Controllers must delegate to Services and should not access Persistence directly.");
@ArchTest
static final ArchRule persistence_should_not_depend_on_controllers = noClasses()
.that().resideInAPackage("..persistence..")
.should().dependOnClassesThat().resideInAPackage("..controller..")
.because("Persistence layer must be independent of the Web/Controller layer.");
@ArchTest
static final ArchRule exceptions_should_be_isolated = noClasses()
.that().resideInAPackage("..exception..")
.should().dependOnClassesThat().resideInAnyPackage("..controller..", "..persistence.entities..")
.because("Exceptions should be part of the domain core and independent of infrastructure details.");
@ArchTest
static final ArchRule configuration_should_not_be_accessed_by_domain = noClasses()
.that().resideInAnyPackage("..domain..")
.should().dependOnClassesThat().resideInAPackage("auth_service.configuration..")
.because("Domain logic should not depend on Spring configuration classes.");
@ArchTest
static final ArchRule services_should_be_annotated = classes()
.that().resideInAPackage("..service..")
@@ -82,6 +101,16 @@ class ArchitectureTest {
.should().beAnnotatedWith(org.springframework.stereotype.Service.class)
.because("Classes named *Service should be registered as Spring @Service beans.");
// ===================================================================================
// 5. SHARED PACKAGE RULES
// ===================================================================================
@ArchTest
static final ArchRule shared_should_not_depend_on_domains = noClasses()
.that().resideInAPackage("auth_service.shared..")
.should().dependOnClassesThat().resideInAPackage("auth_service.domain..")
.because("Shared classes should be independent of specific domains.");
@ArchTest
static final ArchRule controllers_should_be_annotated = classes()
.that().resideInAPackage("..controller..")
@@ -1,10 +1,9 @@
package auth_service.configuration.security;
import auth_service.shared.test.AbstractUnitTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@@ -12,8 +11,7 @@ import static org.mockito.Mockito.when;
/**
* Tests for JwtService.
*/
@ExtendWith(MockitoExtension.class)
class JwtServiceTest {
class JwtServiceTest extends AbstractUnitTest {
@Mock
private JwtConfig jwtConfig;
@@ -1,11 +1,11 @@
package auth_service.domain.login.controller;
import auth_service.configuration.security.JwtAuthenticationFilter;
import auth_service.configuration.security.JwtService;
import auth_service.domain.login.controller.dto.request.LoginRequest;
import auth_service.domain.login.exception.InvalidCredentialsException;
import auth_service.domain.login.model.User;
import auth_service.domain.login.service.LoginService;
import auth_service.shared.test.AbstractWebMvcTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
@@ -28,7 +28,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@WebMvcTest(LoginController.class)
@AutoConfigureMockMvc(addFilters = false) // Skip security filters for simple controller test
@AutoConfigureJsonTesters
class LoginControllerTest {
class LoginControllerTest extends AbstractWebMvcTest {
@Autowired
private MockMvc mockMvc;
@@ -36,9 +36,6 @@ class LoginControllerTest {
@MockitoBean
private LoginService loginService;
@MockitoBean
private JwtService jwtService;
@MockitoBean
private JwtAuthenticationFilter jwtAuthenticationFilter; // Needed because it's used in SecurityConfig
@@ -49,9 +46,7 @@ class LoginControllerTest {
void login_Success() throws Exception {
// Arrange
var request = new LoginRequest("test@example.com", "password");
var authenticatedUser = User.builder().id(815L).email("test@example.com").build();
when(loginService.login(any(User.class))).thenReturn(authenticatedUser);
when(jwtService.generateToken("815", "test@example.com")).thenReturn("mock-token");
when(loginService.login(any(User.class))).thenReturn("mock-token");
// Act & Assert
mockMvc.perform(post("/api/auth/login")
@@ -0,0 +1,60 @@
package auth_service.domain.login.persistence;
import auth_service.domain.login.persistence.entities.MinimalUserEntity;
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 static org.junit.jupiter.api.Assertions.*;
@Import(MinimalUserRepositoryImpl.class)
class MinimalUserRepositoryTest extends AbstractPersistenceTest {
@Autowired
private MinimalUserRepository minimalUserRepository;
@Autowired
private TestEntityManager entityManager;
@Test
void findByEmail_Success() {
// Arrange
var email = "minimal@example.com";
var entity = MinimalUserEntity.builder()
.email(email)
.password("password")
.enabled(true)
.build();
entityManager.persist(entity);
entityManager.flush();
// Act
var result = minimalUserRepository.findByEmail(email);
// Assert
assertTrue(result.isPresent());
assertEquals(email, result.get().getEmail());
}
@Test
void updateLoginDate_Success() {
// Arrange
var entity = MinimalUserEntity.builder()
.email("login@example.com")
.password("password")
.enabled(true)
.build();
entity = entityManager.persist(entity);
entityManager.flush();
// Act
minimalUserRepository.updateLoginDate(entity.getId());
entityManager.clear(); // Clear cache to force reload from DB
// Assert
var updated = entityManager.find(MinimalUserEntity.class, entity.getId());
assertNotNull(updated.getLastLoginDate());
}
}
@@ -4,12 +4,11 @@ import auth_service.domain.login.exception.InvalidCredentialsException;
import auth_service.domain.login.exception.UserNotFoundException;
import auth_service.domain.login.model.User;
import auth_service.domain.login.persistence.MinimalUserRepository;
import auth_service.shared.test.AbstractUnitTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.Optional;
@@ -21,8 +20,7 @@ import static org.mockito.Mockito.when;
/**
* Tests for LoginService.
*/
@ExtendWith(MockitoExtension.class)
class LoginServiceTest {
class LoginServiceTest extends AbstractUnitTest {
@Mock
private MinimalUserRepository minimalUserRepository;
@@ -30,6 +28,9 @@ class LoginServiceTest {
@Mock
private PasswordEncoder passwordEncoder;
@Mock
private TokenGenerator tokenGenerator;
@InjectMocks
private LoginService loginService;
@@ -47,17 +48,19 @@ class LoginServiceTest {
void login_Success() {
// Arrange
var dbUser = User.builder()
.id(815L)
.email("test@example.com")
.password("encodedPassword")
.build();
when(minimalUserRepository.findByEmail(user.getEmail())).thenReturn(Optional.of(dbUser));
when(passwordEncoder.matches(user.getPassword(), dbUser.getPassword())).thenReturn(true);
when(tokenGenerator.generateToken("815", "test@example.com")).thenReturn("mock-token");
// Act
var result = loginService.login(user);
// Assert
assertEquals(dbUser, result);
assertEquals("mock-token", result);
}
@Test
@@ -6,6 +6,7 @@ import auth_service.domain.registration.controller.dto.request.RegistrationReque
import auth_service.domain.registration.exception.EmailAlreadyInUseException;
import auth_service.domain.registration.model.Registration;
import auth_service.domain.registration.service.RegistrationService;
import auth_service.shared.test.AbstractWebMvcTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
@@ -28,7 +29,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@WebMvcTest(RegistrationController.class)
@AutoConfigureMockMvc(addFilters = false) // Skip security filters for simple controller test
@AutoConfigureJsonTesters
class RegistrationControllerTest {
class RegistrationControllerTest extends AbstractWebMvcTest {
@Autowired
private MockMvc mockMvc;
@@ -0,0 +1,78 @@
package auth_service.domain.registration.persistence;
import auth_service.domain.registration.model.Registration;
import auth_service.domain.registration.persistence.entities.RegisteredUserEntity;
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 static org.junit.jupiter.api.Assertions.*;
@Import(RegisteredUserRepositoryImpl.class)
class RegisteredUserRepositoryTest extends AbstractPersistenceTest {
@Autowired
private RegisteredUserRepository registeredUserRepository;
@Autowired
private TestEntityManager entityManager;
@Test
void existsByEmail_Success() {
// Arrange
var email = "exists@example.com";
var entity = RegisteredUserEntity.builder()
.email(email)
.password("password")
.enabled(true)
.steamId(111L)
.registrationDate(java.time.LocalDateTime.now())
.build();
entityManager.persist(entity);
entityManager.flush();
// Act & Assert
assertTrue(registeredUserRepository.existsByEmail(email));
assertFalse(registeredUserRepository.existsByEmail("other@example.com"));
}
@Test
void existsBySteamId_Success() {
// Arrange
var steamId = 222L;
var entity = RegisteredUserEntity.builder()
.email("steam@example.com")
.password("password")
.enabled(true)
.steamId(steamId)
.registrationDate(java.time.LocalDateTime.now())
.build();
entityManager.persist(entity);
entityManager.flush();
// Act & Assert
assertTrue(registeredUserRepository.existsBySteamId(steamId));
assertFalse(registeredUserRepository.existsBySteamId(333L));
}
@Test
void save_Success() {
// Arrange
var registration = Registration.builder()
.email("save@example.com")
.encryptedPassword("hashed")
.steamId(444L)
.build();
// Act
long id = registeredUserRepository.save(registration);
// Assert
assertTrue(id > 0);
var saved = entityManager.find(RegisteredUserEntity.class, id);
assertNotNull(saved);
assertEquals("save@example.com", saved.getEmail());
}
}
@@ -5,12 +5,11 @@ import auth_service.domain.registration.exception.InvalidInvitationCodeException
import auth_service.domain.registration.exception.SteamIdAlreadyRegisteredException;
import auth_service.domain.registration.model.Registration;
import auth_service.domain.registration.persistence.RegisteredUserRepository;
import auth_service.shared.test.AbstractUnitTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.crypto.password.PasswordEncoder;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -21,8 +20,7 @@ import static org.mockito.Mockito.*;
/**
* Tests for RegistrationService.
*/
@ExtendWith(MockitoExtension.class)
class RegistrationServiceTest {
class RegistrationServiceTest extends AbstractUnitTest {
@Mock
private CodeValidationService codeValidationService;
@@ -8,6 +8,7 @@ import auth_service.domain.user.exception.UserNotFoundException;
import auth_service.domain.user.model.User;
import auth_service.domain.user.model.UserSettings;
import auth_service.domain.user.service.UserService;
import auth_service.shared.test.AbstractWebMvcTest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,7 +35,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@WebMvcTest(UserController.class)
@AutoConfigureMockMvc(addFilters = false)
@AutoConfigureJsonTesters
class UserControllerTest {
class UserControllerTest extends AbstractWebMvcTest {
@Autowired
private MockMvc mockMvc;
@@ -0,0 +1,75 @@
package auth_service.domain.user.persistence;
import auth_service.domain.user.model.UserSettings;
import auth_service.domain.user.persistence.entities.UserEntity;
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 java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
@Import(UserRepositoryImpl.class)
class UserRepositoryTest extends AbstractPersistenceTest {
@Autowired
private UserRepository userRepository;
@Autowired
private TestEntityManager entityManager;
@Test
void findByEmail_Success() {
// Arrange
var email = "test@example.com";
var userEntity = UserEntity.builder()
.email(email)
.password("password")
.enabled(true)
.steamId(123456L)
.registrationDate(LocalDateTime.now())
.build();
entityManager.persist(userEntity);
entityManager.flush();
// Act
var result = userRepository.findByEmail(email);
// Assert
assertTrue(result.isPresent());
assertEquals(email, result.get().getEmail());
}
@Test
void updateSettings_Success() {
// Arrange
var email = "settings@example.com";
var userEntity = UserEntity.builder()
.email(email)
.password("password")
.enabled(true)
.steamId(123456L)
.registrationDate(LocalDateTime.now())
.build();
userEntity = entityManager.persist(userEntity);
entityManager.flush();
var settings = UserSettings.builder()
.language("de")
.theme("dark")
.build();
// Act
var updated = userRepository.updateSettings(userEntity.getId(), 654321L, settings);
// Assert
assertTrue(updated);
var updatedUser = entityManager.find(UserEntity.class, userEntity.getId());
assertEquals(654321L, updatedUser.getSteamId());
assertNotNull(updatedUser.getSettings());
assertEquals("de", updatedUser.getSettings().getLanguage());
}
}
@@ -4,11 +4,10 @@ import auth_service.domain.user.exception.UserNotFoundException;
import auth_service.domain.user.model.User;
import auth_service.domain.user.model.UserSettings;
import auth_service.domain.user.persistence.UserRepository;
import auth_service.shared.test.AbstractUnitTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Optional;
@@ -19,8 +18,7 @@ import static org.mockito.Mockito.*;
/**
* Tests for UserService.
*/
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
class UserServiceTest extends AbstractUnitTest {
@Mock
private UserRepository userRepository;
@@ -0,0 +1,10 @@
package auth_service.shared.test;
import org.junit.jupiter.api.Tag;
/**
* Base class for ArchUnit tests.
*/
@Tag("ArchitectureTest")
public abstract class AbstractArchitectureTest {
}
@@ -0,0 +1,22 @@
package auth_service.shared.test;
import org.junit.jupiter.api.Tag;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* Base class for integration tests.
* Full Spring context with Testcontainers.
*/
@Tag("IntegrationTest")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
public abstract class AbstractIntegrationTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17-alpine");
}
@@ -0,0 +1,24 @@
package auth_service.shared.test;
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.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
/**
* Base class for persistence tests.
* Slices only the persistence layer with Testcontainers.
*/
@Tag("PersistenceTest")
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
public abstract class AbstractPersistenceTest {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17-alpine");
}
@@ -0,0 +1,14 @@
package auth_service.shared.test;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
/**
* Base class for unit tests.
* Isolated from Spring context.
*/
@Tag("UnitTest")
@ExtendWith(MockitoExtension.class)
public abstract class AbstractUnitTest {
}
@@ -0,0 +1,13 @@
package auth_service.shared.test;
import org.junit.jupiter.api.Tag;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
/**
* Base class for WebMvc tests.
* Slices the web layer.
*/
@Tag("WebMvcTest")
@WebMvcTest
public abstract class AbstractWebMvcTest {
}