Testing TDD – Where to Specify Mock Behavior in Given-When-Then Syntax

tddtesting

I am unsure where/how to specify the behavior of a mock in a test scenario when using the Given-When-Then syntax.
It seems to me both Given and When could be correct.

Consider the following example:

  • I want to test the control panel for a car.
  • This panel has a start button for the engine and a LED that shows the engine status.
  • When the user presses the start button, the engine should be started and the LED should be green or red, depending on whether the engine was started successfully.
  • The control panel is the SUT, the engine is mocked.
  • In the specific test scenario, we test what happens when the engine fails to start.

Which of the following Given-When-Thens is the more correct one:

This one:

  • Given a control panel in its initial state
  • And an engine that will fail to start
  • When the start button is pressed
  • Then the LED will become red

Or this one:

  • Given a control panel in its initial state
  • When the start button is pressed
  • And the engine fails to start
  • Then the LED will become red

Personally I feel that the second way reads more natural, but I also feel that the mock behavior should not be part of the action on the SUT.

The example is made up, but the key element here is the action towards the engine that is taken as a consequence of the test action given in the When. I.e. the engine response cannot be phrased as a state (unless one would say "given a malfunctioning engine".)

Best Answer

The scenario should be set up in the Given step. This involves mocking parts of the system. However, a mock might be used in the When step when that's part of the action.

When reading your two scenarios, they both look reasonable as natural language:

  • Given a control panel in its initial state, And an engine that will fail to start, When the start button is pressed, Then the LED will become red.
  • Given a control panel in its initial state, When the start button is pressed, And the engine fails to start, Then the LED will become red.

However, the second variant does not conform to the Given-When-Then structure.

  • Given describes the initial context of the scenario.
  • When describes actions or interaction with the system.
  • Then describes the outcome of the actions.

Both of your scenarios obfuscate the actions by using passive voice: “the button is pressed”. In my experience, it is better to name an actor who interacts with the system (third-person perspective) or to write the scenario from a first-person perspective: “When the driver presses the button” or “When I press then button”.

From this, it is clear that “the engine fails to start” is not an action – it is an outcome. But asserting that as an outcome makes no sense for the scenario that you're trying to test. That the engine will fail to start is an essential part of the context of your scenario, so it should be specified in the Given step.

I would write your scenario as:

Scenario: the engine status LED reports a failing engine.

Given a control panel
And and a broken engine
When the driver starts the car
Then the engine fails to start
And the engine status LED lights up red.

Thanks to Greg Burghardt for pointing out in the comments that the dashboard – not the entire car – might be the system under test, so that the engine might be the actor. This would lead to the following, equally valid scenario:

Scenario: the engine status LED reports a failing engine.

Given a control panel
And that the driver tried to start the engine
When the engine reports a failure
Then the engine status LED lights up red.

Related Topic