Stateful Tests

Last updated Nov 26th, 2022

About this...

Stateful tests are tests against state machines. Ask: "are we testing a transition from one state to another?" or are we just testing "input/output".

🌱 This blog post hasn't fully bloomed. It's very likely to change over the next little while.

What is this?

  • Stateful tests are obviously tests that rely on state
  • What makes these different than other tests?

    • You have to set up the state of the world
    • You usually have to test that the new state of the world is correct
    • You usually have to test that the commands that changed the state of the world were, in fact called, and were called correctly.

State changes

  • What are state changes?
  • A successful command-like operation is a state-change.
  • Examples:

    • A successful save, saving a user aggregate to a userRepo
    • A successful makePurchase call to a Stripe API
    • A successful addRole on a user aggregate

State machines

  • Your application is fundamentally a state machine. We move people from A to B - problem to solution. If your app had 9 different states, from beginning to end, and you wanted to test the transition from state 6 to 7, you'd need to load up the state of the world from 1-6, in order to test that transition. Or at the very least, load up what the state of the world looked like at 6.


  • Why don't you test queries?

    • Because queries don't change the state of the world.
    • Yes, they might return different data which informs the behaviour, sending it down different code paths, but ultimately, there's no point in testing queries for stateful tests.
  • What's the role of queries in tests then?

    • Queries merely return the current state of the world.
    • And depending on that state of the world, our application (a state machine), has to act upon that data in different ways.
    • This is what we care about.
    • "Is my feature/use case behaving the way it should based on this state of the world? Do I get a failure result when I try to do something (ie: perform a transition from one state to the next) at an invalid state? Do I get a failure when I don't provide the appropriate data to perform the transition (the behaviour)?"
  • What's the difference between stateful and stateless tests?

    • State, of course.
    • That is, with stateless tests, we are testing functions or objects which typically live in total isolation. They have no stateful collaborators.
    • Why? Because there is no state to them. Stateless because they themselves have no state. There is no state to them.
    • We are often just testing purely behaviour.
    • Data, behaviour, namespaces

      • Let us remember that the essence of software is solve problems. And that is achieved by gathering data, performing behaviour against that data, and organizing the units of data and behaviour into cohesive namespaces.
    • Do you see how this is much different from a stateless test?