Skip to content

Instantly share code, notes, and snippets.

@PaoloLaurenti
Last active May 9, 2020 10:19
Show Gist options
  • Select an option

  • Save PaoloLaurenti/88c902cc18c63a0a15e9ef3e2e575b42 to your computer and use it in GitHub Desktop.

Select an option

Save PaoloLaurenti/88c902cc18c63a0a15e9ef3e2e575b42 to your computer and use it in GitHub Desktop.

Revisions

  1. PaoloLaurenti revised this gist Nov 15, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion aggregate_case.ex
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    defmodule Mondrian.AggregateCase do
    defmodule MyApp.AggregateCase do
    @moduledoc """
    This module defines the test case to be used by aggregate tests.
    """
  2. PaoloLaurenti revised this gist Nov 15, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion aggregate_case.ex
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@ defmodule Mondrian.AggregateCase do
    quote bind_quoted: [aggregate: aggregate] do
    @aggregate_module aggregate

    import Mondrian.Factory
    import MyApp.Factory

    # Assert that the expected events are returned when the given commands have been executed
    defp assert_events(commands, expected_events) do
  3. PaoloLaurenti renamed this gist Nov 15, 2019. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. PaoloLaurenti created this gist Nov 15, 2019.
    77 changes: 77 additions & 0 deletions Commanded.AggregateCase
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,77 @@
    defmodule Mondrian.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 Mondrian.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