Maintenance: NotificationController - Add comprehensive integration tests#137
Maintenance: NotificationController - Add comprehensive integration tests#137claude[bot] wants to merge 1 commit intomasterfrom
Conversation
…ests Added comprehensive integration test coverage for NotificationController to ensure proper REST API behavior and validation. Test Coverage: - Successful token registration (201 CREATED) - Duplicate token registration handling - Validation failures (blank, whitespace-only, null tokens) - Malformed JSON handling - Missing request body handling - Edge cases (long tokens, special characters) All tests use @IntegrationTEST with @AutoConfigureMockMvc to verify the full request/response cycle including validation and error handling through the ControllerAdvice. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
PR Review: NotificationController Integration TestsOverviewThis PR adds comprehensive integration test coverage for the Critical Issues1. Test Isolation & Race Condition RiskLocation: The test // verify - should only have one token
then(tokenRepository.findAll()).hasSize(1);Problem: The verification happens outside the transaction boundary. Between the second POST request completing and the Impact: This could lead to flaky tests in CI/CD environments. Recommendation: Move the verification inside a transactional context or use 2. Potential Database Column Length Constraint MissingLocation: The test verifies that 200-character tokens work: String longToken = "a".repeat(200);Problem: The @Id
private String token; // No @Column(length = ...) specifiedSecurity/Data Integrity Risk:
Recommendation: Add explicit column constraints: @Id
@Column(length = 255) // or appropriate length based on FCM token max length
private String token;3. Missing Token Format ValidationLocation: Controller validation only checks Problem: The current validation accepts any non-blank string, including:
Security Risk: While the token is used as a primary key (reducing SQL injection risk), there's no validation that the token is actually a valid FCM token format. Recommendation: Add format validation: public record NotificationCreateTokenRequest(
@NotBlank(message = "Token is required")
@Pattern(regexp = "^[A-Za-z0-9:_.-]+$", message = "Invalid token format")
String token
) {}Code Quality Issues4. Inconsistent Test Naming Between LayersLocation: Service tests vs Controller tests The service layer test ( // Firebase Cloud Messaging tokens are typically 152+ charactersBut the controller test ( // Firebase Cloud Messaging tokens can be 152+ charactersIssue: Inconsistent documentation ("typically" vs "can be") and hardcoded 200-character test value without justification. Recommendation:
5. Duplicate Test CoverageLocation: Several tests duplicate service layer coverage:
Issue: These tests don't add value at the controller layer since they're testing business logic already covered by service tests. Recommendation: Controller tests should focus on:
Remove tests that purely duplicate service layer behavior. 6. Missing Edge Cases6.1 Content-Type Validation MissingLocation: All POST requests assume Missing test: What happens if someone sends Recommendation: Add test: @Test
void 잘못된_Content_Type으로_요청_시_415_에러를_반환한다() throws Exception {
mockMvc.perform(post("/api/notifications/register")
.contentType(MediaType.TEXT_PLAIN)
.content("plain text"))
.andExpect(status().isUnsupportedMediaType());
}6.2 Token Trimming Behavior UnclearLocation: Question: Should Currently public static NotificationToken create(String token) {
return NotificationToken.builder()
.token(token) // No trimming
.build();
}Recommendation: Either:
Performance Considerations7. Potential N+1 Query Issue (Future Risk)Location: if (!notificationTokenRepository.existsById(token)) {
notificationTokenRepository.save(NotificationToken.create(token));
}Issue: This performs two database operations for new tokens:
Better approach: Use database-level upsert or handle the duplicate key exception: @Transactional
public void registerToken(@NonNull final String token) {
try {
notificationTokenRepository.save(NotificationToken.create(token));
} catch (DataIntegrityViolationException e) {
// Token already exists - this is fine
log.debug("Token already registered: {}", token);
}
}This reduces database round-trips by 50% for new tokens. 8. Missing Test Cleanup VerificationLocation: @AfterEach
void tearDown() {
tokenRepository.deleteAllInBatch();
}Issue: No verification that cleanup actually worked. If cleanup fails, subsequent tests could be affected. Recommendation: Add assertion or use Security Concerns9. No Rate Limiting TestsLocation: Missing entirely Security Risk: The endpoint has no apparent rate limiting. An attacker could:
Recommendation:
@Test
void 동일_IP에서_과도한_요청_시_429_에러를_반환한다() throws Exception {
// Test rate limiting
}10. Missing Authorization/AuthenticationLocation: Security Risk: The endpoint is completely public. Anyone can:
Recommendation: Consider if this endpoint should:
If intentionally public, add a comment explaining why. Testing Best Practices11. Magic Numbers in TestsLocation: Multiple tests use hardcoded strings String token = "valid-fcm-token-123";
String token = "duplicate-token";Issue: Test data lacks consistency and doesn't represent realistic FCM tokens. Recommendation: Create test data constants or fixtures: private static final String VALID_FCM_TOKEN =
"eGhb...YyMzQ1Njc4OTA"; // Realistic FCM token format
private static final String REALISTIC_LONG_TOKEN =
"a".repeat(163); // Actual FCM max length12. Assertion ClarityLocation: .andExpect(jsonPath("$.error.data.token").value("Token is required"));Issue: This hardcodes the error message from the annotation. If the annotation message changes, the test breaks. Recommendation: Either:
.andExpect(jsonPath("$.error.data.token").exists())
.andExpect(jsonPath("$.error.data.token").isNotEmpty());SummaryStrengths
Must Fix
Should Fix
Nice to Have
Test Coverage Score: 7/10The tests cover the happy path and basic validation well, but miss important edge cases, security concerns, and performance optimizations. Overall Recommendation: Request changes before merging. The critical issues (column constraints, format validation, security) should be addressed. |
Summary
Added comprehensive integration test coverage for
NotificationControllerto verify REST API endpoint behavior, validation, and error handling.Area Inspected
NotificationController(src/main/java/spring/memewikibe/api/controller/notification/NotificationController.java)NotificationTokenRegister,NotificationCreateTokenRequest,NotificationTokenIssues Found
Missing Test Coverage: The
NotificationControllerhad no integration tests despite being a public REST API endpoint. While the service layer (NotificationTokenRegister) had comprehensive tests, there was no verification of:ControllerAdviceChanges Made
Created
NotificationControllerTestwith 9 test cases covering:Happy Path
Validation & Error Handling
All tests use
@IntegrationTestwith@AutoConfigureMockMvcto verify the complete request/response cycle including Spring's validation framework and custom error handling.Why This Improves the Code
Test Results
All tests pass:
🤖 Generated with Claude Code