Skip to content

Latest commit

 

History

History
261 lines (204 loc) · 8.7 KB

File metadata and controls

261 lines (204 loc) · 8.7 KB

10. Testing in jPOS Client Implementation

Testing is a crucial part of developing a robust jPOS client. It ensures that your ISO-8583 message creation, sending, and processing work correctly. We'll cover various aspects of testing, including unit tests, integration tests, and simulating server responses.

10.1 Unit Testing

Unit tests are essential for testing individual components of your jPOS client. Let's start with a simple example of testing a message creation service.

import org.jpos.iso.ISOMsg;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class MessageCreationServiceTest {

    @Mock
    private ISOFactory isoFactory;

    @InjectMocks
    private MessageCreationService messageCreationService;

    @Test
    void testCreateAuthorizationRequest() throws Exception {
        // Arrange
        ISOMsg mockMsg = new ISOMsg();
        when(isoFactory.createMsg("0100")).thenReturn(mockMsg);

        // Act
        ISOMsg result = messageCreationService.createAuthorizationRequest("1234567890123456", 100.00);

        // Assert
        assertThat(result).isNotNull();
        assertThat(result.getMTI()).isEqualTo("0100");
        assertThat(result.getString(2)).isEqualTo("1234567890123456");
        assertThat(result.getString(4)).isEqualTo("000000010000");
    }
}

In this example, we're testing the MessageCreationService class, which is responsible for creating ISO-8583 messages. We use Mockito to mock the ISOFactory and AssertJ for fluent assertions.

10.2 Integration Testing

Integration tests ensure that different components of your jPOS client work together correctly. Here's an example of an integration test that sends a message and verifies the response:

import org.jpos.iso.ISOMsg;
import org.jpos.iso.MUX;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
public class TransactionSenderIntegrationTest {

    @Autowired
    private MUX mux;

    @Autowired
    private MessageCreationService messageCreationService;

    @Test
    void testSendAuthorizationRequest() throws Exception {
        // Arrange
        ISOMsg request = messageCreationService.createAuthorizationRequest("1234567890123456", 100.00);

        // Act
        ISOMsg response = mux.request(request, 30000);

        // Assert
        assertThat(response).isNotNull();
        assertThat(response.getMTI()).isEqualTo("0110");
        assertThat(response.getString(39)).isEqualTo("00"); // Assuming '00' is approval code
    }
}

This integration test creates an authorization request, sends it through the MUX, and verifies the response. It uses the actual Spring context, so it's closer to real-world scenarios.

10.3 Simulating Server Responses

To test various scenarios without relying on an actual server, we can use Wiremock to simulate server responses. Here's an example of how to set up a Wiremock server to simulate ISO-8583 responses:

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.channel.NACChannel;
import org.jpos.iso.packager.GenericPackager;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.assertj.core.api.Assertions.assertThat;

public class ISOClientWiremockTest {

    private WireMockServer wireMockServer;
    private NACChannel channel;

    @BeforeEach
    void setup() throws Exception {
        wireMockServer = new WireMockServer(WireMockConfiguration.options().port(8888));
        wireMockServer.start();

        GenericPackager packager = new GenericPackager("packager/iso87ascii.xml");
        channel = new NACChannel("localhost", 8888, packager);
        channel.connect();
    }

    @AfterEach
    void teardown() {
        channel.disconnect();
        wireMockServer.stop();
    }

    @Test
    void testAuthorizationRequest() throws Exception {
        // Arrange
        String responseHex = "30313130F23C46D129E09180000000000000001000000000000010000301000000301000012345678901234560000";
        wireMockServer.stubFor(any(urlEqualTo("/"))
                .willReturn(aResponse()
                        .withStatus(200)
                        .withBody(hexStringToByteArray(responseHex))));

        // Act
        ISOMsg request = new ISOMsg();
        request.setMTI("0100");
        request.set(2, "1234567890123456");
        request.set(4, "000000010000");
        
        ISOMsg response = channel.send(request);

        // Assert
        assertThat(response).isNotNull();
        assertThat(response.getMTI()).isEqualTo("0110");
        assertThat(response.getString(39)).isEqualTo("00");
    }

    private byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }
}

This test sets up a Wiremock server to simulate an ISO-8583 server. It stubs a response for any incoming request and then sends a request using the NACChannel. The test verifies that the response is correctly parsed and contains the expected data.

10.4 Testing with Q2

jPOS provides a Q2 container that can be useful for testing. Here's an example of how to set up a test using Q2:

import org.jpos.q2.Q2;
import org.jpos.q2.iso.QMUX;
import org.jpos.util.NameRegistrar;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

public class Q2Test {

    private static Q2 q2;

    @BeforeAll
    static void setup() throws Exception {
        q2 = new Q2();
        q2.start();
        Thread.sleep(2000); // Wait for Q2 to start
    }

    @AfterAll
    static void teardown() {
        q2.stop();
    }

    @Test
    void testQMUX() throws Exception {
        QMUX qmux = (QMUX) NameRegistrar.get("mux.mymux");
        assertThat(qmux).isNotNull();
        assertThat(qmux.isConnected()).isTrue();

        ISOMsg msg = new ISOMsg("0800");
        msg.set(11, "000001");
        msg.set(70, "301");

        ISOMsg response = qmux.request(msg, 30000);
        assertThat(response).isNotNull();
        assertThat(response.getMTI()).isEqualTo("0810");
        assertThat(response.getString(39)).isEqualTo("00");
    }
}

This test starts a Q2 instance, retrieves a QMUX from the NameRegistrar, and sends a network management request. It then verifies the response.

10.5 Performance Testing

For performance testing, you might want to simulate multiple concurrent requests. Here's a simple example using Java's ExecutorService:

import org.jpos.iso.ISOMsg;
import org.jpos.iso.MUX;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
public class PerformanceTest {

    @Autowired
    private MUX mux;

    @Autowired
    private MessageCreationService messageCreationService;

    @Test
    void testConcurrentRequests() throws Exception {
        int numRequests = 100;
        ExecutorService executor = Executors.newFixedThreadPool(10);
        List<Future<ISOMsg>> futures = new ArrayList<>();

        for (int i = 0; i < numRequests; i++) {
            futures.add(executor.submit(() -> {
                ISOMsg request = messageCreationService.createAuthorizationRequest("1234567890123456", 100.00);
                return mux.request(request, 30000);
            }));
        }

        for (Future<ISOMsg> future : futures) {
            ISOMsg response = future.get();
            assertThat(response).isNotNull();
            assertThat(response.getMTI()).isEqualTo("0110");
            assertThat(response.getString(39)).isEqualTo("00");
        }

        executor.shutdown();
    }
}

This test simulates 100 concurrent authorization requests and verifies that all responses are successful.