Skip to content

Create Custom (Mock) Interaction Semantic #1949

Open
@akefirad

Description

@akefirad

Is your feature request related to a problem?

I'd like to be able t define a custom (mock) interaction semantic for mocking external resources (e.g. MockServer or WireMock) in the then block.

Describe the solution you'd like

As a very simple example, let's say we have user-service which depends on email-service while creating a user for sending email-verification message to the user (i.e. an API call to email-service to send a verification email to the user email address). In a unit test the spec would be something like this:

def 'subject should create a user and send verification email'() {

  given:
    // EmailServiceClient is a feight client poining to email-service
    def emailService = Mock(EmailServiceClient)
    def subject = new UserService(emailService)
    def req = aCreateUserReq()

  when:
    def res = subject.createUser(req)

  then:
    res.status == 200

  and:
    1 * emailService.sendVerificationEmail(_)

}

Now ideally in a (integration) test of the feature I'd love to be able to write something like this:

def 'subject should create a user and send verification email'() {

  given:
    def req = aCreateUserReq() // Now subject is a real bean injected into the test!

  when:
    def res = subject.createUser(req)

  then:
    res.status == 200

  and:
    1 * wiremock.sendVerificationEmail(_) // sendVerificationEmail is just a helper method creating the WireMock stub!

}

Currently this is not gonna work, clearly! For start wiremock is not a mock object, and also the semantic of the interaction mocking is a bit different (in this case, the stub needs to be created right away, i.e. calling WireMock).
Theoretically this should be possible I think, but I don't have deep knowledge about Spock inner details to come up with a solution. Best case scenario is to support both subbing and verification, but for start we can focus on the stubbing part.

Describe alternatives you've considered

Currently I'm putting all wiremock stubs in the given block which is not idea since the rest of the mocks are in the then block. This becomes even uglier for tests with multiple when/then blocks, since the given block is a singleton, the next batch of wiremock stubs (needed for the next when block) has to either live in the given block (which is too far away from the feature being tested; hence less maintainability) or in the relevant when block (which decreases the readability).

Additional context

Let me know if there's anything I need to provide. Thanks.

PS: Great job BTW 👏 !

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions