Skip to content

Latest commit

 

History

History
103 lines (80 loc) · 3.79 KB

File metadata and controls

103 lines (80 loc) · 3.79 KB

Domain Test DSL

Moved into Framework Libraries from its original location as a project in Common Platform. For previous versions please refer here.

A domain-specific language (DSL) for testing aggregate roots and events using domain language:

  • Given/When/Then based
  • Feature files contain scenarios in plain language that business people can understand
  • The Domain Test DSL library automatically tests the Java code implementing aggregate roots according to the behaviour described in the feature files

Example

The implementation of our business domain is event sourced, so we can describe the current state (the Given clause) as a list of events that have already happened. When we perform an action on our domain model (the When clause), the result (the Then clause) will always be a list of events that have now occurred as a consequence:

Scenario: Add ingredients to a recipe

Given recipe added

When you addIngredients to a Recipe from an ingredients list

Then ingredients added

How it works

The language heavily relies on the simple pattern implemented by the Aggregate interface in framework. Every interaction with an aggregate root follows the same pattern:

  1. Events that have occurred previously are applied to the aggregate root
  2. An action is performed on the aggregate root by calling one of its methods with some arguments
  3. Zero or more events are consequently emitted by the aggregate root

Since the Given and Then clauses are simply lists of event descriptions, the only complex part of this is the When clause. In order to interpret this, we need it to follow a fixed grammatical structure:

When you <do something> to an <aggregate root> using <some new information>

  • <do something> is the action being performed, and has to be the method being called on the aggregate root
  • <aggregate root> is the name of the Java class implementing the aggregate root
  • <some new information> is optional, but if present is the data used to perform the action; the arguments passed to the method being called
  • The joining words that can be used are specified by the Domain Test DSL library, but offer a flexible set of choices designed to allow phrases to read as close to well-written English as possible

In terms of the code implementation, events and input data are provided as JSON files. The example scenario above translates to the following steps when running the test:

  1. Create a new instance of the aggregate root class Recipe.
  2. Load some data for a RecipeAdded event from a JSON file called recipe-added.json
  3. Apply the RecipeAdded event to the Recipe aggregate root
  4. Load some data for the action from a JSON file called ingredients-list.json
  5. Call the addIngredients method on the Recipe using the action data
  6. Collect the events emitted from the action method
  7. Assert that the collected events match the event data in a file called ingredients-added.json

recipe-added.json

{
  "_metadata": {
    "name": "recipe-added"
  },
  "recipeId": "5c5a1d30-0414-11e7-93ae-92361f002671",
  "name": "Cheese Cake",
  "glutenFree": true
}

ingredients-list.json

{
  "ingredients": [{
      "name": "sugar",
     "quantity": 500
    }, {
      "name": "custard",
      "quantity": 2
    }
  ]
}

ingredients-added.json

{
  "_metadata": {
    "name": "ingredients-added"
  },
  "recipeId": "5c5a1d30-0414-11e7-93ae-92361f002671",
  "ingredients": [{
      "name": "sugar",
     "quantity": 500
    }, {
      "name": "custard",
      "quantity": 2
    }
  ]
}