Skip to main content

Testing Strategy

WIXY employs a rigorous, two-tier testing strategy that ensures correctness at every layer while maintaining fast feedback cycles. All tests live under a single source root (src/test/java/) with clear separation between unit and integration tests.

Test Pyramid

              ╱ ╲
╱ IT ╲ 57 integration tests
╱──────╲ Full HTTP against running app
╱ Unit ╲ 129 unit tests
╱────────────╲ Isolated, mocked dependencies
TierTestsSpeedScopeTag
Unit129~3 secondsSingle class, mocked dependencies@Tag("unit")
Integration57~15 secondsFull Spring Boot context, real HTTP@Tag("integration")
Total186~18 seconds

Directory Layout

src/test/java/io/github/vinipx/wixy/
├── unit/ ← UNIT TESTS (@Tag("unit"))
│ ├── application/
│ │ └── WixyApplicationTest.java 3 tests
│ ├── config/
│ │ ├── WixyPropertiesTest.java 17 tests
│ │ ├── WireMockConfigTest.java 8 tests
│ │ ├── WireMockHealthIndicatorTest.java 4 tests
│ │ └── SecurityConfigTest.java 13 tests
│ ├── controller/
│ │ ├── AdminControllerTest.java 11 tests
│ │ ├── ProxyControllerTest.java 4 tests
│ │ └── RecordingControllerTest.java 6 tests
│ ├── service/
│ │ ├── StubServiceTest.java 14 tests
│ │ ├── ProxyServiceTest.java 8 tests
│ │ └── RecordingServiceTest.java 8 tests
│ └── exception/
│ └── ExceptionTest.java 16 tests

└── integration/ ← INTEGRATION TESTS (@Tag("integration"))
├── BaseIntegrationTest.java shared superclass
├── config/
│ └── TestEnvironment.java local / remote URL resolution
├── context/
│ └── ApplicationContextIT.java 4 tests
├── health/
│ └── HealthEndpointIT.java 4 tests
├── stub/
│ └── StubManagementIT.java 13 tests
├── proxy/
│ └── ProxyManagementIT.java 7 tests
├── recording/
│ └── RecordingIT.java 6 tests
├── security/
│ └── SecurityIT.java 10 tests
├── swagger/
│ └── SwaggerIT.java 6 tests
└── wiremock/
└── WireMockResolutionIT.java 7 tests

Design Principles

Single Source Root

Both unit and integration tests reside under src/test/java/ — a single Gradle source set. The separation is achieved through:

  1. Directory structureunit/ vs integration/ sub-packages
  2. JUnit 5 tags@Tag("unit") vs @Tag("integration") on every test class
  3. Gradle taskstest (unit only) vs integrationTest (integration only)
  4. Naming convention*Test.java for unit, *IT.java for integration

Mirror-the-Source Principle

Unit test packages mirror the main source structure exactly:

Main SourceUnit Test
io.github.vinipx.wixy.config.SecurityConfigio.github.vinipx.wixy.unit.config.SecurityConfigTest
io.github.vinipx.wixy.service.StubServiceio.github.vinipx.wixy.unit.service.StubServiceTest
io.github.vinipx.wixy.controller.AdminControllerio.github.vinipx.wixy.unit.controller.AdminControllerTest
io.github.vinipx.wixy.exception.*io.github.vinipx.wixy.unit.exception.ExceptionTest

Integration test packages mirror the domain areas they exercise:

DomainIntegration Test
Application bootstrapintegration.context.ApplicationContextIT
Stub CRUD lifecycleintegration.stub.StubManagementIT
Proxy managementintegration.proxy.ProxyManagementIT
Recording lifecycleintegration.recording.RecordingIT
API-key securityintegration.security.SecurityIT

Coverage

JaCoCo enforces a minimum 80% instruction coverage threshold. The current suite achieves:

MetricCoverage
Instruction96.5%
Branch92.0%
Line96.1%
Method97.8%

The build fails if coverage drops below the threshold:

build.gradle.kts
tasks.jacocoTestCoverageVerification {
violationRules {
rule {
limit {
minimum = "0.80".toBigDecimal()
}
}
}
}

Quick Commands

CommandDescription
./gradlew testRun unit tests only (129 tests)
./gradlew integrationTestRun integration tests only (57 tests)
./gradlew checkRun both + JaCoCo coverage verification
./gradlew jacocoTestReportGenerate HTML coverage report
./gradlew integrationTest -Dwixy.test.base-url=https://...Run against a remote instance
tip

For detailed examples and code walkthroughs, see the dedicated Unit Tests and Integration Tests guides.