# Unit Testing Guide This guide explains how to run and write unit tests for the JAX-WS Hello World Service project. ## Quick Start ### Run Tests with Docker (Recommended) #### Windows ```cmd run-tests.bat ``` #### Linux/Mac ```bash ./run-tests.sh ``` ### Run Tests with Maven (Local) If you have Maven installed locally: ```bash mvn test ``` ## Test Results Summary ### Current Test Coverage | Service | Test Class | Test Cases | Status | |---------|-----------|------------|--------| | Hello World Service | HelloWorldServiceImplTest | 10 | ✅ Passing | ### Test Case Details The `HelloWorldServiceImplTest` includes the following test cases: 1. **testGetHelloWorld_WithValidName** - Verifies greeting with valid name 2. **testGetHelloWorld_WithEmptyString** - Handles empty string input 3. **testGetHelloWorld_WithNull** - Handles null input gracefully 4. **testGetHelloWorld_WithSpecialCharacters** - Handles special characters 5. **testGetHelloWorld_WithSpaces** - Handles names with spaces 6. **testGetHelloWorld_WithLongName** - Handles long names 7. **testGetHelloWorld_ReturnsNonNull** - Ensures non-null response 8. **testGetHelloWorld_StartsWithHelloWorld** - Verifies message format 9. **testGetHelloWorld_EndsWithExclamation** - Verifies message ending 10. **testGetHelloWorld_ContainsName** - Verifies name inclusion ## Docker Test Configuration ### Test Architecture The project uses a multi-stage Dockerfile: - **Stage 1 (tester)**: Runs unit tests - **Stage 2 (builder)**: Builds the WAR file - **Stage 3**: Deploys to Tomcat ### Test Docker Compose The `docker-compose.test.yml` file is configured to: - Target the `tester` stage of the Dockerfile - Mount source code for live testing - Cache Maven dependencies for faster subsequent runs - Set appropriate memory limits ### Run Tests Manually ```bash # Build and run tests docker-compose -f docker-compose.test.yml up --build # Clean up after tests docker-compose -f docker-compose.test.yml down ``` ## Testing Framework ### Dependencies The project uses: - **JUnit 5 (Jupiter)** - Testing framework - `junit-jupiter-api:5.9.3` - Test annotations and assertions - `junit-jupiter-engine:5.9.3` - Test execution engine - **Mockito** - Mocking framework (for future complex tests) - `mockito-core:5.3.1` - Core mocking functionality - `mockito-junit-jupiter:5.3.1` - JUnit 5 integration - **Maven Surefire** - Test runner plugin - Configured to run all `*Test.java` files ## Writing New Tests ### Test Structure Tests follow the standard JUnit 5 structure: ```java package com.example.service; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.DisplayName; import static org.junit.jupiter.api.Assertions.*; @DisplayName("Service Tests") class YourServiceTest { private YourService service; @BeforeEach void setUp() { service = new YourServiceImpl(); } @Test @DisplayName("Should do something") void testSomething() { // Arrange String input = "test"; String expected = "expected result"; // Act String result = service.doSomething(input); // Assert assertEquals(expected, result); } } ``` ### Test Best Practices 1. **Use Descriptive Names**: Use `@DisplayName` for readable test descriptions 2. **Follow AAA Pattern**: Arrange, Act, Assert 3. **Test Edge Cases**: Include null, empty, and boundary conditions 4. **Keep Tests Isolated**: Each test should be independent 5. **Test One Thing**: Each test should verify one specific behavior ### Adding Tests for New Services To add tests for other services (e.g., LoanApprovalService): 1. Create test class in `src/test/java/com/example/service/` 2. Follow the naming convention: `{ServiceName}Test.java` 3. Run tests to verify Example structure for LoanApprovalService tests: ```java package com.example.service; import com.example.model.*; import com.example.repository.*; import org.junit.jupiter.api.*; import org.mockito.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @DisplayName("LoanApprovalService Tests") class LoanApprovalServiceTest { @Mock private CustomerRepository customerRepository; @Mock private CreditScoreService creditScoreService; private LoanApprovalService service; @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); service = new LoanApprovalService(); // Inject mocks if needed } @Test @DisplayName("Should approve loan for high credit score") void testLoanApproval_HighCreditScore() { // Test implementation } } ``` ## Test Directory Structure ``` src/ ├── main/ │ └── java/ │ └── com/ │ └── example/ │ └── service/ │ ├── HelloWorldService.java │ └── HelloWorldServiceImpl.java └── test/ └── java/ └── com/ └── example/ └── service/ └── HelloWorldServiceImplTest.java ``` ## Continuous Integration ### Running Tests in CI/CD The Dockerfile includes testing as the first stage, which means: - Tests run automatically during Docker build - Build fails if tests fail - Ensures code quality before deployment To run tests in CI/CD pipelines: ```bash # Option 1: Run full build (includes tests) docker build -t jaxws-app . # Option 2: Run tests only docker build --target tester -t jaxws-test . # Option 3: Use docker-compose docker-compose -f docker-compose.test.yml up --abort-on-container-exit ``` ## Viewing Test Reports ### Console Output Test results are displayed in the console with summary: ``` ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.example.service.HelloWorldServiceImplTest Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.024 s Results: Tests run: 10, Failures: 0, Errors: 0, Skipped: 0 BUILD SUCCESS ``` ### Surefire Reports Maven Surefire generates detailed reports in: - `target/surefire-reports/` (text and XML formats) ## Troubleshooting ### Tests Not Running **Problem**: Maven doesn't find tests **Solution**: - Ensure test files end with `Test.java` - Verify test directory structure: `src/test/java/` - Check pom.xml includes maven-surefire-plugin ### Docker Build Fails on Tests **Problem**: Docker build fails at test stage **Solution**: ```bash # View detailed test output docker build --target tester -t jaxws-test . # Check test container logs docker logs ``` ### Dependency Issues **Problem**: Cannot resolve JUnit dependencies **Solution**: ```bash # Clear Maven cache and rebuild docker-compose -f docker-compose.test.yml build --no-cache ``` ### Permission Denied on run-tests.sh **Problem**: Cannot execute run-tests.sh on Linux/Mac **Solution**: ```bash chmod +x run-tests.sh ./run-tests.sh ``` ## Future Enhancements Consider adding tests for: 1. **LoanApprovalService** - Customer registration workflows - Loan approval logic - Credit score evaluation - Blacklist handling 2. **Repository Layer** - Database operations - CRUD functionality - Error handling 3. **Integration Tests** - End-to-end SOAP request/response - Database integration - Multi-service workflows 4. **Performance Tests** - Load testing - Stress testing - Response time validation ## Resources - [JUnit 5 User Guide](https://junit.org/junit5/docs/current/user-guide/) - [Mockito Documentation](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html) - [Maven Surefire Plugin](https://maven.apache.org/surefire/maven-surefire-plugin/) - [Test-Driven Development Best Practices](https://martinfowler.com/bliki/TestDrivenDevelopment.html) ## Summary This project now has a complete unit testing setup with: - ✅ JUnit 5 testing framework - ✅ 10 passing test cases for HelloWorldService - ✅ Docker-based test execution - ✅ Convenient test runner scripts - ✅ Multi-stage Dockerfile with test stage - ✅ Maven Surefire configuration - ✅ Mockito for future mocking needs To add more tests, simply create new test classes following the established patterns and run them using the provided scripts.