Deploying and controlling external mocks

We just saw how to connect a system test against a running enterprise application. But how can we control and manipulate the external system that is used inside the application's use case?

An external system can be mocked away using mock server technology such as WireMock. WireMock runs as a standalone web server, which is configured to answer specific requests accordingly. It acts like a code level test mock object, that stubs and verifies behavior.

The benefit of using container orchestration frameworks for system tests is that services can be easily replaced by mock servers. The external system's infrastructure as code configuration for the system test environment can contain a WireMock Docker image, which is executed instead of the actual system.

The following code snippet shows an example Kubernetes configuration for the assembly line system, using a WireMock Docker image in the running pods:

---
kind: Service
apiVersion: v1
metadata:
  name: assembly-line
  namespace: systemtest
spec:
  selector:
    app: assembly-line
  ports:
    - port: 8080
---
kind: Deployment
apiVersion: apps/v1beta1
metadata:
  name: assembly-line
  namespace: systemtest
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: assembly-line
    spec:
      containers:
      - name: assembly-line
        image: docker.example.com/wiremock:2.6
      restartPolicy: Always
---

The system test connects against this service, using an administration URL to set up and modify the mock server's behavior.

The following code snippet shows an implementation of the AssemblyLine test delegate, using the WireMock API to control the service:

import static com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder.okForJson;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static java.util.Collections.singletonMap;

public class AssemblyLine {

    public void initBehavior() {
        configureFor("http://test.assembly.example.com", 80);
        resetAllRequests();

        stubFor(get(urlPathMatching("/assembly-line/processes/[0-9A-Z]+"))
                .willReturn(okForJson(singletonMap("status", "IN_PROGRESS"))));

        stubFor(post(urlPathMatching("/assembly-line/processes"))
                .willReturn(status(202)));
    }

    public void verifyInstructions(String id) {
        verify(postRequestedFor(urlEqualTo("/assembly-line/processes/" + id))
                .withRequestBody(carProcessBody()));
    }

    ...
}

The initial behavior instructs the WireMock instance to answer HTTP requests appropriately. The behavior can also be modified during the test case, if more complex processes and conversations have to be represented.

If a more sophisticated test scenario involves asynchronous communication such as long-running processes, the test cases can use polling to wait for verifications.

The defined car manufacturer and assembly line delegates can be reused within multiple test scenarios. Some cases might require to run system tests mutually exclusively.

In the Maintaining test data and scenarios section, we will see what further methods and approaches support developers in writing maintainable test cases.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.182.62