{"id":16323745,"url":"https://github.com/shavo007/spring-integ-demo","last_synced_at":"2026-04-17T05:02:20.261Z","repository":{"id":37941988,"uuid":"374581697","full_name":"shavo007/spring-integ-demo","owner":"shavo007","description":null,"archived":false,"fork":false,"pushed_at":"2023-03-20T22:58:05.000Z","size":671,"stargazers_count":0,"open_issues_count":7,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-23T22:57:07.781Z","etag":null,"topics":["docker","integration-testing","junit5","spring-boot","testcontainers","testcontainers-junit-jupiter"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shavo007.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-07T07:56:00.000Z","updated_at":"2021-12-07T05:06:44.000Z","dependencies_parsed_at":"2024-11-06T16:42:46.700Z","dependency_job_id":null,"html_url":"https://github.com/shavo007/spring-integ-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/shavo007/spring-integ-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shavo007%2Fspring-integ-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shavo007%2Fspring-integ-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shavo007%2Fspring-integ-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shavo007%2Fspring-integ-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shavo007","download_url":"https://codeload.github.com/shavo007/spring-integ-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shavo007%2Fspring-integ-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31915900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T18:22:33.417Z","status":"online","status_checked_at":"2026-04-17T02:00:06.879Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","integration-testing","junit5","spring-boot","testcontainers","testcontainers-junit-jupiter"],"created_at":"2024-10-10T22:55:33.507Z","updated_at":"2026-04-17T05:02:20.234Z","avatar_url":"https://github.com/shavo007.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring integration tests\n\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/shavo007/spring-integ-demo/actions/workflows/push.yml\"\u003e\n    \u003cimg src=\"https://github.com/shavo007/spring-integ-demo/actions/workflows/push.yml/badge.svg\" alt=\"CI\" style=\"max-width: 100%;\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/shavo007/spring-integ-demo/actions/workflows/codeql.yml\"\u003e\n    \u003cimg src=\"https://github.com/shavo007/spring-integ-demo/actions/workflows/codeql.yml/badge.svg\" alt=\"CodeQL\" style=\"max-width: 100%;\"\u003e\n  \u003c/a\u003e\n \u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Dependabot-active-brightgreen.svg\" alt=\"Dependabot Badge\"\u003e\n  \u003cimg src=\"https://img.shields.io/github/languages/code-size/shavo007/spring-integ-demo\" alt=\"GitHub code size in bytes\"\u003e\n  \u003cimg src=\"https://img.shields.io/github/commit-activity/w/shavo007/spring-integ-demo\" alt=\"GitHub commit activity\"\u003e\n  \u003ca href=\"https://github.com/shavo007/spring-integ-demo/issues\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/issues/shavo007/spring-integ-demo\" alt=\"GitHub issues\"\u003e\n  \u003c/a\u003e\n\n![customer API arch](./assets/ArchDiagram.png)\n\n\u003e Integration testing is a healthy part of the [test pyramid](https://martinfowler.com/articles/practical-test-pyramid.html)\n\n- **Improved portability**: Mocking your dependencies with testcontainers allows you to run your tests anywhere Docker is installed. It removes the need for username/password credentials and open ports to the external network, and the overall overhead associated with these resources.\n- **Known stateful setup**: Utilizing testcontainers allows you to have the same consistent state before every run of your functional test. This reduces the reliance on a proper test state in your real dependencies. The  **“ephemeral”** nature of docker containers helps. ie. we mean that the container can be stopped and destroyed, then rebuilt and replaced with an absolute minimum set up and configuration.\n\n## Definition of an integration test\n\n An integration test can be any of the following:\n\n- a test that covers multiple “units”. It tests the interaction between two or more clusters of cohesive classes.\n- a test that covers multiple layers. This is actually a specialization of the first case and might cover the interaction between a business service and the persistence layer, for instance.\n- a test that covers the whole path through the application. In these tests, we send a request to the application and check that it responds correctly and has changed the database state according to our expectations.\n\n## Test showcases\n\n- [CustomerFullBlownIT](./src/test/java/com/example/integdemo/CustomerFullBlownIT.java)showcase full blown integ test with db (bootstraps entire web container) `mvn test -Dtest=CustomerFullBlownIT`\n- [CustomerFullBlownEmbeddedIT](./src/test/java/com/example/integdemo/CustomerFullBlownEmbeddedIT.java) showcase full blown integ test with embedded db (bootstraps spring app context but not starts server) `mvn test -Dtest=CustomerFullBlownEmbeddedIT`\n- [CustomerFullBlownTestConIT](./src/test/java/com/example/integdemo/CustomerFullBlownTestConIT.java)showcase full blown integ test with testcontainer db (bootstraps entire web container) `mvn test -Dtest=CustomerFullBlownTestConIT`\n- [CustomerControllerIT](./src/test/java/com/example/integdemo/CustomerControllerIT.java) showcase integ test with only web layer (not start http server) `mvn test -Dtest=CustomerControllerIT`\n- [CustomerThirdPartyAPIIT](./src/test/java/com/example/integdemo/CustomerThirdPartyAPIIT.java) showcase generic container to test out integration with 3rd party API `mvn test -Dtest=CustomerThirdPartyAPIIT`\n- [CustomerS3LocalStackIT](./src/test/java/com/example/integdemo/CustomerS3LocalStackIT.java) AWS s3 example with localstack `mvn test -Dtest=CustomerS3LocalStackIT`\n- [CustomerGithubActionsIT](./src/test/java/com/example/integdemo/CustomerGithubActionsIT.java) showcase running as github action with docker containers `mvn test -Dtest=CustomerGithubActionsIT`\n- [CustomerRestAssuredIT](./src/test/java/com/example/integdemo/CustomerRestAssuredIT.java) showcase using restAssured `mvn test -Dtest=CustomerRestAssuredIT`\n- [CustomerControllerExceptionHandIT](./src/test/java/com/example/integdemo/CustomerControllerExceptionHandIT.java) showcase exception handling `mvn test -Dtest=CustomerControllerExceptionHandIT`\n\n## Mvn failsafe plugin\n\nRun all integration tests\n\n```bash\nmvn -V -ff verify\n```\n\n## Considerations\n\n- `Do not run unit and integ tests together` (use diff src sets or use maven failsafe plugin)\n- Caution when Customizing the Application Context : Each customization of the application context is one more thing that makes it different from the \"real\" application context that is started up in a production setting. So, in order to make our tests as close to production as we can, we should only customize what's really necessary to get the tests running!\n- The benefit of Testcontainers is that the database always starts in a known state, without any contamination between test runs or on developers' local machines.\n- If our PostgreSQL container is going to listen to a random port every time, then we should somehow set and change the `spring.datasource.url` configuration property dynamically. Solution is to use Spring `@DynamicPropertySource`\n\n## Start the app\n\n```bash\n#can create a docker compose file here instead\ndocker run --name postgres-demo -e POSTGRES_PASSWORD=root -p 5432:5432 -d postgres:11\ndocker run -d -p8090:8081 shanelee007/greetings-api:latest\ndocker run -d -p 4566:4566 -p 4571:4571 localstack/localstack -e \"SERVICES=dynamodb,s3\"\n\nmvn spring-boot:run\n```\n\n```bash\ndocker exec -it postgres-demo bash\npsql -d postgres -U postgres\n\\l #list databases\n\\dt #list tables\n\\dn #list schemas\n\\s #command history\n\nSELECT * from customer;\n```\n\n## Junit insights report\n\n![sample report](./assets/insights.png)\n\n## Performance\n\nBEFORE\n```bash\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  01:30 min\n[INFO] Finished at: 2021-07-06T21:59:11+10:00\n[INFO] ------------------------------------------------------------------------\n```\n\nAFTER with parallel execution\n```bash\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  01:15 min\n[INFO] Finished at: 2021-07-06T22:30:02+10:00\n[INFO] ------------------------------------------------------------------------\n```\n\n```xml\n  \u003cconfigurationParameters\u003e\n           junit.jupiter.execution.parallel.enabled=true\n           junit.jupiter.execution.parallel.mode.default=concurrent\n           junit.jupiter.execution.parallel.mode.classes.default=concurrent\n         \u003c/configurationParameters\u003e\n```\n\n## Resources\n\n- [test slices](https://docs.spring.io/spring-boot/docs/current/reference/html/test-auto-configuration.html)\n- [test insights](https://github.com/adessoAG/junit-insights)\n- [dynamically set config](https://www.baeldung.com/spring-dynamicpropertysource)\n- [test containers database](https://www.testcontainers.org/modules/databases/)\n- [maven failsafe plugin](https://www.baeldung.com/maven-integration-test#failsafe)\n- [quirks of testconfiguration](https://www.sivalabs.in/2020/12/quirks-of-spring-testconfiguration/)\n- [test containers demo](https://github.com/drjunior90/testcontainers-demo)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshavo007%2Fspring-integ-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshavo007%2Fspring-integ-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshavo007%2Fspring-integ-demo/lists"}