Skip to content

add a 'double' package that distinguishes Stubs, Spies and Mocks #1631

Closed

Description

@laurentdutheil

Description

If we refer to a definition of test doubles, there is an interest in distinguishing stubs, spies and mocks.

Stubs provide canned answers to calls made during the test. For example, a stub needs to return a value in response of a query. If the code under test changes and no longer needs to make that
query, there is no reason that the test should break.

Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.

Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are
checked during verification to ensure they got all the calls they were expecting.

We can see the separation of concern between them as:

  • a Stub handles the predefined calls
  • a Spy is a Stub who records the actual calls.
  • a Mock is a Spy who can make assertions and fail the tests on error.
classDiagram
    Stub <|-- Spy
    Spy <|-- Mock

    class Stub {
        - predefinedCalls
        + Called()
        + On()
        ...()
    }
    class Spy {
        - actualCalls
        + NumberOfCalls()
        ...()
    }
    class Mock {
        + AssertCalled()
        ...()
    }

Loading

Proposed solution

There is a POC here

I try to explain the design choices in Architecture Decision Records.
All the ADR are negotiable, except perhaps the first one which is the purpose of the POC.

Opinion:

  • a Stub should fail the test if we don't know what to return
  • a Stub should not fail the test if a prepared call is not called
  • a Stub should not fail the test if a method without return argument was not in the prepared calls

The POC introduces reflection (to know if a method have return parameters) and generics (to propose a constructor for Stubs, Spies and Mocks)

The purpose is to be as retro-compatible as possible to facilitate the migration.

It is opinionated. So I'll understand a reject. Even so, it was fun to code.

Use case

There is a comparison between the actual library and the proposition.

There is also examples of Stub, Spy and Mock

References

Can be referred to #483

Activity

  1. locked and limited conversation to collaborators on Sep 29, 2024
  2. converted this issue into a discussion #1643 on Sep 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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