Testing
Because your domain is described a series of pure functions, testing becomes ultra-simple: given some input, expect a certain output. No mocking calls to external services or a database.

Actions

Let's look at the basic example from the Domain page:
actions.js
1
const actions = {
2
addTodo: (state, payload) => {
3
if (!payload.title) throw new Error('titleMissing')
4
5
return [{
6
type: 'TodoAdded',
7
title: payload.title,
8
at: Date.now(),
9
}]
10
}
11
}
12
13
module.exports = actions
Copied!
Now let's write a test for this.
__test__/actions.js
1
// stub Date.now
2
Date.now = () => 123
3
4
const test = require('tape')
5
const actions = require('../actions')
6
7
test('addTodo', assert => {
8
assert.deepEquals(
9
actions.addTodo({}, { title: 'foobar' }),
10
[{
11
type: 'TodoAdded',
12
title: 'foobar',
13
at: 123
14
}],
15
'generates a TodoAdded event'
16
)
17
18
assert.throws(
19
() => actions.addTodo({}, { foo: 'bar' }),
20
/titleMissing/,
21
'throws if title is missing'
22
)
23
})
Copied!
And we can even execute it:

Reducer

reducer.js
1
const initialState = {
2
todos: []
3
}
4
5
const reducer = (state, event) => {
6
switch (event.type) {
7
case 'TodoAdded':
8
return {
9
todos: [
10
...state.todos,
11
{ title: event.title },
12
]
13
}
14
15
default:
16
return state
17
}
18
}
19
20
module.exports = (events, state=initialState) => events.reduce(reducer, state)
Copied!
__test__/reducer.js
1
const test = require('tape')
2
const reducer = require('../reducer')
3
4
test('todoReducer', assert => {
5
const events = [
6
{ type: 'TodoAdded', title: 'get milk' },
7
{ type: 'TodoAdded', title: 'borrow sugar' },
8
{ type: 'Invalid', title: 'ignore this' },
9
]
10
11
const expected = {
12
todos: [
13
{ title: 'get milk' },
14
{ title: 'borrow sugar' },
15
]
16
}
17
18
const result = reducer(events)
19
20
assert.deepEquals(result, expected, 'reduces events')
21
assert.end()
22
})
Copied!
Last modified 2yr ago
Copy link