testing
Load when writing tests, modifying test infrastructure, working with E2E test base classes, or improving test coverage.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Load when writing tests, modifying test infrastructure, working with E2E test base classes, or improving test coverage.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Load when developing API endpoints, designing request/response DTOs, creating controllers, or working with BaseResponse wrapper and exception handling patterns.
Load when designing new domains or modules, refactoring architecture, working with Clean Architecture layers, ports/adapters pattern, or cross-domain communication.
Commit, push, and open a PR following project conventions. Use when creating pull requests.
GitHub PR의 코드 리뷰 코멘트를 읽어와 피드백을 반영하고, 각 코멘트에 답글을 남깁니다.
프로젝트 컨벤션에 맞는 일관된 커밋 메시지를 생성하고 커밋을 수행합니다.
Create a GitHub issue following project conventions. Use when creating issues.
| name | testing |
| description | Load when writing tests, modifying test infrastructure, working with E2E test base classes, or improving test coverage. |
Load this context when writing or modifying tests.
| Type | When to Write | Coverage Goal |
|---|---|---|
| E2E | Required for ALL API endpoints | 100% endpoint coverage |
| Unit | Complex logic, exception-heavy code | Selective |
Philosophy: Prefer E2E tests over unit tests. Unit tests only when logic is complex enough to warrant isolated testing.
// All E2E tests extend from E2ETestBase
abstract class E2ETestBase {
@Autowired
protected lateinit var tokenProvider: AuthTokenProvider
@Autowired
protected lateinit var userRepository: UserRepository
@AfterEach
protected open fun tearDown() {
userRepository.deleteAllInBatch()
}
// Create test user and get JWT token
fun createTestUserAndToken(
email: String = "test-${System.currentTimeMillis()}@example.com",
name: String = "Test User",
providerType: ProviderType = ProviderType.TEST,
): Pair<User, String>
}
Reference: src/test/kotlin/com/neki/e2e/E2ETestBase.kt
For domain-specific setup, extend the domain base class:
// Photo domain tests
class CreateFolderE2ETest : FolderE2ETestBase() {
// FolderE2ETestBase extends E2ETestBase
// Adds folder-specific setup/teardown
}
src/test/kotlin/com/neki/
├── e2e/ # E2E tests (organized by domain)
│ ├── E2ETestBase.kt # Base class for all E2E tests
│ ├── auth/
│ │ └── AuthE2ETest.kt
│ ├── photo/
│ │ └── folder/
│ │ ├── FolderE2ETestBase.kt
│ │ ├── CreateFolderE2ETest.kt
│ │ ├── DeleteFolderE2ETest.kt
│ │ ├── GetAllFolderE2ETest.kt
│ │ └── UpdateFolderE2ETest.kt
│ └── user/
│ └── UserE2ETest.kt
├── auth/ # Unit tests (next to domain)
│ └── infra/security/filter/
│ └── AuthMdcFilterTest.kt
├── common/
│ └── filter/
│ └── RequestMdcFilterTest.kt
└── JasyptTest.kt # Utility tests
@Test
fun `should create folder successfully`() {
// 1. Create test user and get token
val (user, token) = createTestUserAndToken()
// 2. Make authenticated request
RestAssured.given()
.header("Authorization", "Bearer $token")
.contentType(ContentType.JSON)
.body(CreateFolderRequest(name = "My Folder"))
.`when`()
.post("/api/folders")
.then()
.statusCode(200)
.body("success", equalTo(true))
.body("data.folderId", notNullValue())
}
@Test
fun `should return error when folder name duplicated`() {
val (user, token) = createTestUserAndToken()
// Create first folder
createFolder(token, "Duplicate Name")
// Try to create duplicate
RestAssured.given()
.header("Authorization", "Bearer $token")
.contentType(ContentType.JSON)
.body(CreateFolderRequest(name = "Duplicate Name"))
.`when`()
.post("/api/folders")
.then()
.statusCode(400)
.body("resultCode", equalTo("D-06")) // CONFLICT_FOLDER
}
Tests run with @ActiveProfiles("test"):
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
class MyE2ETest : E2ETestBase() {
// ...
}
| Tool | Purpose |
|---|---|
| Kotest | Test framework with DSL |
| MockK | Mocking library for Kotlin |
| RestAssured | HTTP testing |
| Testcontainers | Database containers |
Encrypt sensitive values for configuration:
// src/test/kotlin/com/neki/JasyptTest.kt
@Test
fun jasyptGeneratTest() {
val text = "value_to_encrypt"
val encrypted = jasyptStringEncryptor.encrypt(text)
println("ENC($encrypted)")
}
createFavoritePhotoImage in
PhotoImageE2ETestBaseExample:
// ✅ GOOD: Helper in base class
abstract class PhotoImageE2ETestBase : E2ETestBase() {
protected fun createFavoritePhotoImage(
userId: Long,
mediaId: Long,
folderId: Long? = null
): PhotoImage {
val photo = createPhotoImage(userId, mediaId, folderId)
favoritePhotoRepository.save(
FavoritePhoto(userId = userId, imageId = photo.id!!)
)
return photo
}
}
// ❌ BAD: Duplicating same helper in multiple test files
class GetFavoritePhotosE2ETest : PhotoImageE2ETestBase() {
fun createFavoritePhotoImage(...) { /* duplicate! */
}
}
Delete dependent entities FIRST to respect foreign key constraints:
@AfterEach
override fun tearDown() {
favoritePhotoRepository.deleteAllInBatch() // Dependent first
photoImageRepository.deleteAllInBatch() // Parent second
folderRepository.deleteAllInBatch()
mediaRepository.deleteAllInBatch()
super.tearDown()
}
@AfterEach (delete dependent entities first)