This commit is contained in:
2026-04-28 01:24:04 +09:30
parent 914521f376
commit 29e8a32864
16 changed files with 445 additions and 315 deletions
+76 -25
View File
@@ -2,20 +2,42 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.gradle.jvm.toolchain.JavaLanguageVersion
import java.sql.DriverManager
// Version strings for libraries
val postgresqlVersion: String = "42.7.10"
val flywayVersion: String = "12.4.0"
val jooqVersion: String = "3.21.0"
val logbackVersion: String = "1.5.0"
val springSecurityVersion: String = "6.3.1"
val springdocOpenApiVersion: String = "2.5.0"
val jacksonVersion: String = "2.18.0"
val commonsLang3Version: String = "3.14.0"
val guavaVersion: String = "33.1.0-jre"
val lombokVersion: String = "1.18.30"
val junitVersion: String = "5.10.2"
val mockitoVersion: String = "5.11.0"
val testcontainersVersion: String = "1.20.0"
val h2Version: String = "2.3.232"
val restAssuredVersion: String = "5.4.0"
buildscript {
dependencies {
classpath("org.postgresql:postgresql:42.7.10")
classpath("org.flywaydb:flyway-database-postgresql:12.4.0")
}
}
plugins {
id("org.springframework.boot") version "3.2.5"
id("io.spring.dependency-management") version "1.1.4"
id("org.openapi.generator") version "7.4.0"
id("org.springframework.boot") version "4.0.+"
id("io.spring.dependency-management") version "1.1.6"
id("org.openapi.generator") version "7.6.0"
id("nu.studer.jooq") version "9.0"
id("org.flywaydb.flyway") version "12.4.0"
id("application")
id("java")
}
val postgresqlVersion: String by project
val flywayVersion: String by project
val jooqVersion: String by project
val logbackVersion: String by project
group = "net.moustos"
version = "0.1.0"
@@ -32,36 +54,42 @@ dependencies {
implementation("org.postgresql:postgresql:$postgresqlVersion")
implementation("org.flywaydb:flyway-core:$flywayVersion")
implementation("org.flywaydb:flyway-database-postgresql:$flywayVersion")
implementation("org.jooq:jooq:$jooqVersion")
implementation("org.jooq:jooq-meta:$jooqVersion")
implementation("org.jooq:jooq-codegen:$jooqVersion")
jooqGenerator("org.postgresql:postgresql:$postgresqlVersion")
jooqGenerator("org.jooq:jooq:$jooqVersion")
jooqGenerator("org.jooq:jooq-meta:$jooqVersion")
jooqGenerator("org.jooq:jooq-codegen:$jooqVersion")
implementation("com.auth0:java-jwt:4.4.0")
implementation("org.springframework.security:spring-security-crypto:6.2.3")
implementation("org.springframework.security:spring-security-crypto:$springSecurityVersion")
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.1")
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:$springdocOpenApiVersion")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jacksonVersion")
implementation("ch.qos.logback:logback-core:$logbackVersion")
implementation("ch.qos.logback:logback-classic:$logbackVersion")
implementation("net.logstash.logback:logstash-logback-encoder:7.4")
implementation("net.logstash.logback:logstash-logback-encoder:8.0")
compileOnly("org.projectlombok:lombok:1.18.30")
annotationProcessor("org.projectlombok:lombok:1.18.30")
compileOnly("org.projectlombok:lombok:$lombokVersion")
annotationProcessor("org.projectlombok:lombok:$lombokVersion")
implementation("org.apache.commons:commons-lang3:3.14.0")
implementation("com.google.guava:guava:33.1.0-jre")
implementation("org.apache.commons:commons-lang3:$commonsLang3Version")
implementation("com.google.guava:guava:$guavaVersion")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.security:spring-security-test")
testImplementation("org.testcontainers:testcontainers:1.19.7")
testImplementation("org.testcontainers:postgresql:1.19.7")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
testImplementation("org.mockito:mockito-core:5.7.1")
testImplementation("org.mockito:mockito-junit-jupiter:5.7.1")
testImplementation("io.rest-assured:rest-assured:5.4.0")
testImplementation("org.testcontainers:testcontainers:$testcontainersVersion")
testImplementation("org.testcontainers:junit-jupiter:$testcontainersVersion")
testImplementation("org.testcontainers:postgresql:$testcontainersVersion")
testImplementation("com.h2database:h2:$h2Version")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
testImplementation("org.mockito:mockito-core:$mockitoVersion")
testImplementation("org.mockito:mockito-junit-jupiter:$mockitoVersion")
testImplementation("io.rest-assured:rest-assured:$restAssuredVersion")
}
java {
@@ -98,7 +126,14 @@ openApiGenerate {
))
}
flyway {
url = project.property("db.url") as String
user = project.property("db.user") as String
password = project.property("db.password") as String
}
jooq {
version.set("$jooqVersion")
configurations {
create("main") {
jooqConfiguration.apply {
@@ -125,16 +160,26 @@ jooq {
}
fun isPostgresAvailable(): Boolean {
val dbUrl = project.property("db.url") as String
val dbUser = project.property("db.user") as String
logger.lifecycle("Checking PostgreSQL availability at $dbUrl with user $dbUser")
return try {
DriverManager.setLoginTimeout(2)
DriverManager.getConnection(project.property("db.url") as String, project.property("db.user") as String, project.property("db.password") as String).use { true }
// Load the PostgreSQL driver
Class.forName("org.postgresql.Driver")
DriverManager.setLoginTimeout(10)
DriverManager.getConnection(dbUrl, dbUser, project.property("db.password") as String).use { connection ->
logger.lifecycle("Successfully connected to PostgreSQL database.")
true
}
} catch (ex: Exception) {
logger.warn("PostgreSQL is unavailable at configured DB; skipping jOOQ code generation.")
logger.error("Failed to connect to PostgreSQL at $dbUrl with user $dbUser: ${ex.message}")
logger.error("Exception details: ", ex)
false
}
}
tasks.named("generateJooq") {
dependsOn("flywayMigrate")
onlyIf {
isPostgresAvailable()
}
@@ -146,6 +191,12 @@ tasks.named("generateJooq") {
}
}
tasks.named("flywayMigrate") {
onlyIf {
isPostgresAvailable()
}
}
tasks.named("compileJava") {
dependsOn("openApiGenerate")
}
+11 -22
View File
@@ -38,9 +38,12 @@ spring:
max-request-size: 10MB
server:
port: ${server.port:8080}
port: 8080
servlet:
context-path: ${server.servlet.contextPath:/}
context-path: /
compression:
enabled: true
min-response-size: 1024
app:
jwt:
@@ -50,8 +53,14 @@ app:
logging:
level:
root: ${log.level:INFO}
net.moustos.mtgsearch: DEBUG
org.springframework.web: INFO
org.springframework.security: DEBUG
config: classpath:logback-spring.xml
file:
name: ${log.dir:logs}/app.log
max-size: 100MB
max-history: 30
springdoc:
api-docs:
@@ -61,23 +70,3 @@ springdoc:
enabled: true
operations-sorter: method
tags-sorter: alpha
server:
port: 8080
servlet:
context-path: /
compression:
enabled: true
min-response-size: 1024
logging:
level:
root: INFO
net.moustos.mtgsearch: DEBUG
org.springframework.web: INFO
org.springframework.security: DEBUG
config: classpath:logback-spring.xml
file:
name: logs/mtg-search.log
max-size: 100MB
max-history: 30
@@ -12,6 +12,7 @@ import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import net.moustos.mtgsearch.repository.UserRepository;
/**
* Integration tests for authentication API
@@ -24,9 +25,13 @@ public class AuthControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private UserRepository userRepository;
@BeforeEach
public void setUp() {
// Clear database before each test
userRepository.deleteAll();
}
@Test
@@ -6,20 +6,40 @@ import org.junit.jupiter.api.DisplayName;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import net.moustos.mtgsearch.model.User;
import net.moustos.mtgsearch.repository.UserRepository;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Disabled;
/**
* Unit tests for AuthService
*/
@SpringBootTest
@TestPropertySource(locations = "classpath:application-test.yml")
@Testcontainers
@Disabled("Requires Docker for Testcontainers")
@DisplayName("AuthService Tests")
public class AuthServiceTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
.withDatabaseName("mtgsearch_test")
.withUsername("postgres")
.withPassword("postgres");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired
private AuthService authService;
@@ -4,18 +4,38 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import net.moustos.mtgsearch.model.User;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Disabled;
/**
* Tests for UserRepository
*/
@SpringBootTest
@TestPropertySource(locations = "classpath:application-test.yml")
@Testcontainers
@Disabled("Requires Docker for Testcontainers")
public class UserRepositoryTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
.withDatabaseName("mtgsearch_test")
.withUsername("postgres")
.withPassword("postgres");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired
private UserRepository userRepository;
@@ -2,22 +2,14 @@ spring:
profiles:
active: test
datasource:
url: jdbc:postgresql://localhost:5432/mtgsearch_test
username: postgres
password: postgres
driver-class-name: org.postgresql.Driver
hikari:
maximum-pool-size: 5
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
jpa:
database-platform: org.hibernate.dialect.PostgreSQLDialect
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create-drop
show-sql: false
flyway:
enabled: true
baseline-on-migrate: true
enabled: false
app:
jwt: