Skip to content
Snippets Groups Projects
bdd-with-cucumber.adoc 4.12 KiB

BDD with Cucumber

Introduction

Starting with Epic-654 (Bidirektionale Kommunikation in .NET- und Java-SDKs), we tried to define formal acceptance criteria with Gherkin. Gherkin is a so-called BDD language (Behaviour Driven Design), i.e., it allows to specify behaviour using a semiformal approach of mixing keywords with English (or other) language fragments.

Example:

Gherkin example (first Acceptance criterion)
  Scenario: Optional callback-URL is used upon a new submission
    Given a sender created a sender client
    And the sender creates a new submission
    And used a callback-URL with secret
    And sets FIT-Connect as reply-channel
    When the sender submits the new submission
    Then the submission contains the callback-URL
    And the submission contains the secret
    And FIT-Connect is set as reply-channel

Each statement can then be implemented as a so-called test step in Java (or other languages) using frameworks like Cucumber (for Java), or SpecFlow (for .NET/C#).

The implementation of a step might look like this:

Java implementation of a particular test step
    @And("the submission contains the secret")
    public void theSubmissionContainsTheSecret() {
        assertThat(createSubmission.getCallback().getSecret(), is(CALLBACK_SECRET));
    }

Here we make sure that the submitted metadata (i.e., the payload to a put request) contains the desired reply channel. We do not test getters/setters of Java objects, but the logic of the SDK itself, without making a call to the service itself (using some mock objects).

Test flow

Normal Integration Tests

The integration tests implemented so far, always perform a round trip from the test suite via the SDK to the submission service. Therefore, they can only indirectly check whether the implemented calls had correct payloads.

normal-integration-tests

BDD Integration Tests

The BDD based tests should not require a running submission service. Nevertheless, we would like to test sent data by intercepting the backend calls with mock objects. Then it is possible to test the behaviour of the SDK itself by validating the HTTP payload which was handed over to the HTTP Client.

bdd-integration-tests

An implementation of such a mock interception looks like this:

when(httpClientMock.post(anyString(), anyMap(),
        any(CreateSubmission.class), eq(CreatedSubmission.class))) (1)
        .thenAnswer(new Answer() {
            public Object answer(InvocationOnMock invocation) {
                createSubmission
                        = invocation.getArgument(2); (2)
                return (new HttpResponse<CreatedSubmission>(200, createdSubmission));
            }
        });
1 When the post request to create a new submission is executed
2 We store the create object to verify later whether it contained the correct data, cf. Java implementation of a particular test step

Caveats

The current implementation contains two challenges with the used version of PowerMock which need bo be addressed in the future.

  • PowerMock should support mocking of private methods. For some reason we could not make use of this feature but had to make the respective calls protected (cf. respective TODOs in the source of ClientFactory).

  • PowerMock only works with JUnit 4 so far. There is a JUnit 5 extension prepared already, cf. powermock/pull/1146.

    For a local build it is currently recommended to check out/clone https://github.com/ascheman/powermock/tree/junit-jupiter-extension.

    Running ./gradlew publishToMavenLocal will install the proper version (2.0.10).