-
Notifications
You must be signed in to change notification settings - Fork 0
Maintenance: NotificationController - Add comprehensive integration tests #137
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
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 <[email protected]>
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