Service API Testing

1. Overview

Testing in the Service API project is structured to balance speed, reliability, and coverage. A combination of unit tests, integration tests, and SOAP API tests ensures confidence in business logic, service interaction, and external system integration.

Tests are organized by type and placed alongside the code they validate (typically in src/test/java). Each test type serves a specific purpose:

  • Unit Tests: Fast and isolated. Ideal for verifying business logic, utility methods, and TR-069 parameter transformations.

  • Integration Tests: Validate how components interact in a realistic Spring Boot context with simulated ACS connections.

  • SOAP API Tests: End-to-end tests validating the SOAP endpoints and their contract.

2. Best Practices

  • Follow naming conventions like *Test or *IT to distinguish between unit and integration tests.

  • Use @MockBean to isolate external dependencies in integration tests, especially ACS connections.

  • Use @ActiveProfiles("test") to activate test-specific configurations.

  • Prefer readable assertions (assertThat, assertEquals, etc.) over excessive mocking.

  • Avoid external dependencies or shared state between tests unless explicitly required.

  • For SOAP testing, use the Spring WS test utilities to validate request/response structures.

3. Coverage Goals

  • The project enforces a minimum of 80% code coverage via JaCoCo.

  • All new code should be accompanied by appropriate tests.

  • Focus on testing meaningful business logic, not just line coverage.

  • Core TR-069 parameter handling and SOAP API functionality should aim for near 100% coverage.

4. Unit Tests Example

  • Focus on individual components (e.g., service methods or delegates) in isolation.

  • Use @ExtendWith(MockitoExtension.class) for mocking dependencies with Mockito.

  • Example of testing TR-069 parameter processing:

@ExtendWith(MockitoExtension.class)
public class WirelessParameterConverterTest {

    @InjectMocks
    private WirelessParameterConverter converter;

    @Mock
    private DeviceRepository deviceRepository;

    @Test
    void shouldConvertTr098ToTr181Format() {
        // Given
        WirelessParameter parameter = new WirelessParameter();
        parameter.setName("SSID");
        parameter.setValue("TestNetwork");

        Device device = new Device();
        device.setDataModel(DataModel.TR_181);
        when(deviceRepository.findBySerialNumber("00908F123456")).thenReturn(Optional.of(device));

        // When
        WirelessParameter result = converter.convertParameter("00908F123456", parameter);

        // Then
        assertEquals("Device.WiFi.SSID.1.SSID", result.getPath());
        assertEquals("TestNetwork", result.getValue());
    }
}

5. SOAP API Tests Example

  • Test the SOAP interface endpoints directly using Spring WS testing utilities.

  • Validate both request marshalling and response handling.

  • Example:

@SpringBootTest
@ActiveProfiles("test")
public class FTServiceUpdateWirelessTest {

    @Autowired
    private ApplicationContext applicationContext;

    @MockBean
    private WirelessService wirelessService;

    @Test
    void testUpdateWirelessRequest() throws Exception {
        // Given
        when(wirelessService.updateWireless(any(UpdateWirelessRequest.class)))
            .thenReturn(createSuccessResponse());

        // The SOAP request XML
        String request =
            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " +
            "xmlns:fri=\"http://www.friendly-tech.com/\">" +
            "<soapenv:Body>" +
            "<fri:FTServiceUpdateWireless>" +
            "<fri:sn>00908F27ea9c</fri:sn>" +
            "<fri:instance>1</fri:instance>" +
            "<fri:securityType>wpa2</fri:securityType>" +
            "<fri:encryptionKey>1414141414</fri:encryptionKey>" +
            "<fri:reprovision>0</fri:reprovision>" +
            "</fri:FTServiceUpdateWireless>" +
            "</soapenv:Body>" +
            "</soapenv:Envelope>";

        // When/Then
        MockWebServiceClient mockClient = MockWebServiceClient.createClient(applicationContext);

        mockClient.sendRequest(withPayload(new StringSource(request)))
            .andExpect(payload(containsString("<ResponseCode>100</ResponseCode>")))
            .andExpect(payload(containsString("<Status>Completed</Status>")));

        verify(wirelessService).updateWireless(any(UpdateWirelessRequest.class));
    }

    private UpdateWirelessResponse createSuccessResponse() {
        UpdateWirelessResponse response = new UpdateWirelessResponse();
        ResponseStatus status = new ResponseStatus();
        status.setResponseCode(100);
        status.setStatus("Completed");
        response.setResponse(status);
        return response;
    }
}

6. Configuration Tests

Service API relies heavily on YAML configuration for various features. Tests should verify:

  • Proper parsing of service-api.yml file

  • Validation of TR-069 parameter paths

  • Custom configurations for specific device models

Example test:

@SpringBootTest
@ActiveProfiles("test")
public class ServiceApiConfigurationTest {

    @Autowired
    private SubscriptionConfiguration subscriptionConfig;

    @Autowired
    private WirelessConfiguration wirelessConfig;

    @Test
    void shouldLoadSubscriptionConfigurationForDevice() {
        // Given
        String deviceModel = "AudioCodes MP262";

        // When
        List<SubscriptionParameter> parameters =
            subscriptionConfig.getWirelessParametersForDevice(deviceModel);

        // Then
        assertNotNull(parameters);
        assertFalse(parameters.isEmpty());

        // Verify specific parameter
        Optional<SubscriptionParameter> ssidParam = parameters.stream()
            .filter(p -> p.getPath().contains("SSID"))
            .findFirst();

        assertTrue(ssidParam.isPresent());
        assertEquals("Friendly-1", ssidParam.get().getActiveValue());
    }
}

7. Running Tests

To execute tests and generate a coverage report, use the following command:

./gradlew clean test

Coverage report path:

build/reports/jacoco/test/html/index.html