Skip to content

QA: Implement Testcontainers #77#84

Merged
omatheusmesmo merged 16 commits intoomatheusmesmo:developfrom
Gustavo-Felix:issue77
Mar 12, 2026
Merged

QA: Implement Testcontainers #77#84
omatheusmesmo merged 16 commits intoomatheusmesmo:developfrom
Gustavo-Felix:issue77

Conversation

@Gustavo-Felix
Copy link
Copy Markdown
Contributor

@Gustavo-Felix Gustavo-Felix commented Feb 28, 2026

fixes #77

Description

Currently, integration tests rely on mocked or local configurations, which may not fully represent real infrastructure behavior. To improve test reliability, consistency, and confidence, we should introduce Testcontainers to run integration tests against real, isolated services using Docker.

Resolution (What was done)

  • Dependency Management: Added Testcontainers dependencies to the project to support container orchestration during the test lifecycle.

  • Reusable Infrastructure: Configured reusable containers (database) to ensure each test suite runs in a clean, isolated environment.

  • Standardization: Applied the new integration test strategy across the project, replacing mocks with real service instances.

How to Test

Prerequisite: Ensure Docker is installed and running on your machine.

  • Execution: Run your standard build command ./mvnw verify.

  • Log Validation: Observe the console logs to confirm the automatic startup of the containers (e.g., Creating container for image: postgres:18).

  • Verification: Confirm that all integration tests pass using the real connection established by Testcontainers.

Acceptance Criteria

  • Testcontainers dependencies are correctly integrated.

  • Database containers start and stop automatically during test execution.

  • Integration tests run successfully using Testcontainers.

@omatheusmesmo
Copy link
Copy Markdown
Owner

Fix #77

@omatheusmesmo omatheusmesmo requested review from Copilot and omatheusmesmo and removed request for Copilot March 1, 2026 13:41
@omatheusmesmo omatheusmesmo self-assigned this Mar 1, 2026
Copy link
Copy Markdown
Owner

@omatheusmesmo omatheusmesmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request #84 Review: Implement Testcontainers for Integration Testing

Hello @Gustavo-Felix! Thank you for the excellent work on this PR. Implementing Testcontainers is a major step forward for ShoppMate, ensuring our integration tests run against a real PostgreSQL environment.

I have validated your original implementation logic, and it works as expected. However, I identified a critical compatibility issue with modern Docker Engines (like the one in my environment) and would like to suggest some architectural improvements to align with our project standards.

1. Version Upgrade: Testcontainers 2.0.3

Your original PR used version 2.0.2 (which seemed to have some metadata issues) and triggered a Docker API version mismatch (client version 1.32 is too old. Minimum supported API version is 1.44).

  • Validation: I updated the dependencies to Testcontainers 2.0.3. This version correctly negotiates the API with modern Docker Servers (API 1.44+).
  • Recommendation: Use the testcontainers-bom to manage versions consistently across all modules.

2. Package Structure Alignment (Architectural Suggestion)

Currently, the integration tests are in a global IntegrationTests package. To maintain our feature-based structure:

  • Recommendation: Move the controller tests to their respective feature packages. For example, CategoryControllerWithIntegrationTest should be in com.omatheusmesmo.shoppmate.category.controller (under src/test/java).
  • Recommendation: Move AbstractIntegrationTest to a shared package like com.omatheusmesmo.shoppmate.shared.testcontainers.

3. JWE Integration and Constructor Injection

I noticed that TestUserFactory uses field injection (@Autowired) and manually persists users to generate tokens.

  • JWE Alignment: We should use our real JwtService (JWE implementation) directly in tests. Since JwtService only needs a UserDetails object to sign a token, we can generate tokens without always hitting the database, making tests faster and more decoupled.
  • Constructor Injection: To stay consistent with our clean code standards, please refactor test components (like TestUserFactory) to use constructor-based injection.

4. Security Configuration (CSRF)

The addition of CsrfCookieFilter and the explicit activation of CSRF protection is great! It ensures our tests simulate a production-hardened environment for SPAs. No risks were identified in the security changes.

Final Validation Result

The original logic is sound and the tests pass perfectly once the library versions are adjusted. By applying the suggested refactorings, the PR will not only provide better QA but also maintain high architectural consistency.

Great job! 🚀

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 1, 2026

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 1, 2026

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 1, 2026

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 1, 2026

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 1, 2026

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 1, 2026

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 1, 2026

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

Copy link
Copy Markdown
Owner

@omatheusmesmo omatheusmesmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @Gustavo-Felix! Thank you for the updates. I've reviewed the changes you made based on our previous feedback, and I can see that the infrastructure is much more aligned with our project standards now.

Great job on applying the following:

  • Testcontainers BOM (2.0.3): Versioning is now handled correctly and centrally.
  • Package Structure: The reorganization into feature packages is perfect.
  • Constructor Injection: The TestUserFactory is much cleaner now.
  • CSRF Implementation: Security configuration is now reflecting our production needs.

⚠️ Remaining Issue: Integration Test Failure

Despite the improvements in the structure, we still have a failing test that is blocking the CI:

Error: expected: <Book Putted> but was: <Food> in testGetAllCategories

Technical Root Cause:

The root cause of this failure is test interdependency and lack of isolation. Although the infrastructure is ready, the test logic itself is still fragile:

  • Assertion by Index: Using categories.get(0) assumes that the list will always be in a specific order and that no other data (like <Food> from a migration) exists.
  • Order Dependency (@Order): Relying on one test to set the state for the next is a risky pattern. If any test in the chain fails, it causes a "domino effect" on the others.

🛠️ Final Recommendation: Test Independence (F.I.R.S.T.)

To finalize this PR, we should follow the "Independent" principle of F.I.R.S.T. tests:

  1. Remove @Order: Tests should be able to run in any sequence (or in parallel) without failing.
  2. Isolation: Use @BeforeEach to clean the repository (e.g., repository.deleteAll()) or annotate the class with @Transactional so each test rolls back its changes.
  3. Self-Contained Data: Each test should create exactly the data it needs to validate its logic, rather than relying on the result of the previous method.

Suggested Adjustment:

Update the assertion to check for the existence of the item in the list, rather than its position:

// Instead of categories.get(0)
assertTrue(categories.stream().anyMatch(c -> c.name().equals("Book Putted")));

🚀 Conclusion

We are almost there! Once we decouple the test logic and ensure each method is independent, this PR will be 100% solid and ready for merging.

Thanks for the persistence and the great work so far! 👏

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 8, 2026

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 8, 2026

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

@omatheusmesmo omatheusmesmo self-requested a review March 12, 2026 00:35
Copy link
Copy Markdown
Owner

@omatheusmesmo omatheusmesmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job @Gustavo-Felix , thanks for your effort! Wonderful first PR 🎉

@omatheusmesmo
Copy link
Copy Markdown
Owner

Hi @Gustavo-Felix! I’ve analyzed the CI logs for the failure in Backend Build and Test.

While the logs show FATAL: role "root" does not exist, this is actually background noise from the GitHub Actions service healthcheck (it tries to ping the DB using the default 'root' user). The real blocker causing the ApplicationContext failure is the hardcoded port 8080 (DEFINED_PORT).

GitHub Runners often have port 8080 restricted or already in use, which prevents the Spring Boot server from starting, leading to the IllegalState error we see in the logs.

To fix this and make the CI 'green', we should move to RANDOM_PORT.

Files to modify:

  1. AbstractIntegrationTest.java:
    Change the annotation to:

    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
  2. CategoryControllerWithIntegrationTest.java (and ItemControllerWithIntegrationTest.java):
    Inject the dynamic port and use it in the init() method:

    @LocalServerPort
    private int port;
    
    @BeforeEach
    void init() {
        // ... code to get jwtToken and csrfToken
        specification = new RequestSpecBuilder()
                .setPort(port) // Use the injected random port here
                .setBasePath("/category")
                .addHeader("Authorization", "Bearer " + jwtToken)
                .addHeader("X-XSRF-TOKEN", csrfToken)
                .addCookie("XSRF-TOKEN", csrfToken)
                .setContentType(ContentType.JSON)
                .addFilter(new RequestLoggingFilter(LogDetail.ALL))
                .addFilter(new ResponseLoggingFilter(LogDetail.ALL))
                .build();
    }

This change will ensure the tests are fully isolated and resilient to the CI environment. Great work on the Testcontainers setup otherwise! 🚀"

  • backend/src/test/java/com/omatheusmesmo/shoppmate/shared/testcontainers/AbstractIntegrationTest.java
  • backend/src/test/java/com/omatheusmesmo/shoppmate/category/controller/CategoryControllerWithIntegrationTest.java
  • backend/src/test/java/com/omatheusmesmo/shoppmate/item/controller/ItemControllerWithIntegrationTest.java

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

@omatheusmesmo
Copy link
Copy Markdown
Owner

Hi @Gustavo-Felix! Great progress with the RANDOM_PORT fix. The logs now show that we've cleared the port conflict, but we've hit the next blocker: the missing RSA certificates.

The RsaKeyConfig class is failing because it cannot find certs/public_key.pem in the CI environment. Since we don't commit production keys to the repo, we need to provide dummy keys specifically for the test suite.

Action required:

  1. Create the following directory: backend/src/test/resources/certs/
  2. Generate a pair of non-sensitive dummy RSA keys into that folder using these commands:
    # Private Key
    openssl genrsa -out backend/src/test/resources/certs/private_key.pem 2048
    
    # Public Key (Extracted from Private Key)
    openssl rsa -in backend/src/test/resources/certs/private_key.pem -pubout -out backend/src/test/resources/certs/public_key.pem
    Alternatively, you can use an online RSA generator like cryptotools.net and save the outputs as .pem files.
  3. Commit these dummy files.

Why this works:
During testing, Spring prioritizes src/test/resources over src/main/resources. By placing dummy keys there, the ApplicationContext will find the 'files' it needs to load the security context in the CI, without compromising our production security.

Once these files are added, the CI should finally turn green! 🚀

@omatheusmesmo omatheusmesmo self-requested a review March 12, 2026 01:17
@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Hi @Gustavo-Felix, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 I'm sorry @Gustavo-Felix, but I was unable to process your request. Please see the logs for more details.

Copy link
Copy Markdown
Owner

@omatheusmesmo omatheusmesmo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job!

@omatheusmesmo omatheusmesmo merged commit a753e54 into omatheusmesmo:develop Mar 12, 2026
13 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants