Last active
May 9, 2020 10:19
-
-
Save PaoloLaurenti/88c902cc18c63a0a15e9ef3e2e575b42 to your computer and use it in GitHub Desktop.
A proposal for the Commanded AggregateCase that allows to test aggregates states
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.AggregateCase do | |
@moduledoc """ | |
This module defines the test case to be used by aggregate tests. | |
""" | |
use ExUnit.CaseTemplate | |
using aggregate: aggregate do | |
quote bind_quoted: [aggregate: aggregate] do | |
@aggregate_module aggregate | |
import MyApp.Factory | |
# Assert that the expected events are returned when the given commands have been executed | |
defp assert_events(commands, expected_events) do | |
assert_events([], commands, expected_events) | |
end | |
defp assert_events(initial_events, commands, expected_events) do | |
{_aggregate, events, error} = aggregate_run(initial_events, commands) | |
actual_events = List.wrap(events) | |
assert is_nil(error) | |
assert actual_events == expected_events | |
end | |
defp assert_state(commands, expected_state) do | |
assert_state([], commands, expected_state) | |
end | |
defp assert_state(initial_events, commands, expected_state) do | |
{aggregate, events, error} = aggregate_run(initial_events, commands) | |
assert is_nil(error) | |
assert aggregate == expected_state | |
end | |
defp assert_error(commands, expected_error) do | |
assert_error([], commands, expected_error) | |
end | |
defp assert_error(initial_events, commands, expected_error) do | |
{_aggregate, _events, error} = aggregate_run(initial_events, commands) | |
assert error == expected_error | |
end | |
defp aggregate_run(initial_events, commands) do | |
%@aggregate_module{} | |
|> evolve(initial_events) | |
|> execute(commands) | |
end | |
# Execute one or more commands against an aggregate | |
defp execute(aggregate, commands) do | |
commands | |
|> List.wrap() | |
|> Enum.reduce({aggregate, [], nil}, fn | |
command, {aggregate, _events, nil} -> | |
case @aggregate_module.execute(aggregate, command) do | |
{:error, reason} = error -> {aggregate, nil, error} | |
events -> {evolve(aggregate, events), events, nil} | |
end | |
_command, {aggregate, _events, _error} = reply -> | |
reply | |
end) | |
end | |
# Apply the given events to the aggregate state | |
defp evolve(aggregate, events) do | |
events | |
|> List.wrap() | |
|> Enum.reduce(aggregate, &@aggregate_module.apply(&2, &1)) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment