Packages
commanded
0.15.0
1.4.10
1.4.9
1.4.8
1.4.7
1.4.6
1.4.3
1.4.2
1.4.1
1.4.0
1.4.0-rc.0
1.3.1
1.3.0
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.1
1.0.0-rc.0
0.19.1
0.19.0
0.18.1
0.18.0
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.16.0-rc.1
0.16.0-rc.0
0.15.1
0.15.0
0.14.0
0.14.0-rc.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.5
0.8.4
0.8.3
0.8.1
0.8.0
0.7.1
0.6.2
0.6.1
0.6.0
0.4.0
0.3.1
0.3.0
0.2.1
0.2.0
0.1.0
Use Commanded to build your own Elixir applications following the CQRS/ES pattern.
Current section
Files
Jump to
Current section
Files
test/event/handle_event_test.exs
defmodule Commanded.Event.HandleEventTest do
use Commanded.StorageCase
import Commanded.Enumerable, only: [pluck: 2]
import Commanded.Assertions.EventAssertions
alias Commanded.EventStore
alias Commanded.Event.{AppendingEventHandler,UninterestingEvent}
alias Commanded.Helpers.EventFactory
alias Commanded.Helpers.{ProcessHelper,Wait}
alias Commanded.ExampleDomain.BankAccount.AccountBalanceHandler
alias Commanded.ExampleDomain.BankAccount.Events.{BankAccountOpened,MoneyDeposited}
setup do
on_exit fn ->
ProcessHelper.shutdown(AccountBalanceHandler)
ProcessHelper.shutdown(AppendingEventHandler)
end
end
test "should be notified of events" do
{:ok, handler} = AccountBalanceHandler.start_link()
events = [
%BankAccountOpened{account_number: "ACC123", initial_balance: 1_000},
%MoneyDeposited{amount: 50, balance: 1_050}
]
recorded_events = EventFactory.map_to_recorded_events(events)
send(handler, {:events, recorded_events})
Wait.until(fn ->
assert AccountBalanceHandler.current_balance == 1_050
end)
end
test "should ignore uninterested events" do
{:ok, handler} = AccountBalanceHandler.start_link()
# include uninterested events within those the handler is interested in
events = [
%UninterestingEvent{},
%BankAccountOpened{account_number: "ACC123", initial_balance: 1_000},
%UninterestingEvent{},
%MoneyDeposited{amount: 50, balance: 1_050},
%UninterestingEvent{}
]
recorded_events = EventFactory.map_to_recorded_events(events)
send(handler, {:events, recorded_events})
Wait.until(fn ->
assert AccountBalanceHandler.current_balance == 1_050
end)
end
test "should ignore events created before the event handler's subscription when starting from `:current`" do
stream_uuid = UUID.uuid4
initial_events = [%BankAccountOpened{account_number: "ACC123", initial_balance: 1_000}]
new_events = [%MoneyDeposited{amount: 50, balance: 1_050}]
{:ok, 1} = EventStore.append_to_stream(stream_uuid, 0, Commanded.Event.Mapper.map_to_event_data(initial_events, UUID.uuid4(), UUID.uuid4(), %{}))
wait_for_event BankAccountOpened
{:ok, handler} = AppendingEventHandler.start_link(start_from: :current)
assert GenServer.call(handler, :last_seen_event) == nil
{:ok, 2} = EventStore.append_to_stream(stream_uuid, 1, Commanded.Event.Mapper.map_to_event_data(new_events, UUID.uuid4(), UUID.uuid4(), %{}))
wait_for_event MoneyDeposited
Wait.until(fn ->
assert AppendingEventHandler.received_events() == new_events
[ metadata ] = AppendingEventHandler.received_metadata()
assert Map.get(metadata, :event_number) == 2
assert Map.get(metadata, :stream_id) == stream_uuid
assert Map.get(metadata, :stream_version) == 2
assert %NaiveDateTime{} = Map.get(metadata, :created_at)
assert GenServer.call(handler, :last_seen_event) == 2
end)
end
test "should receive events created before the event handler's subscription when starting from `:origin`" do
stream_uuid = UUID.uuid4
initial_events = [%BankAccountOpened{account_number: "ACC123", initial_balance: 1_000}]
new_events = [%MoneyDeposited{amount: 50, balance: 1_050}]
{:ok, 1} = EventStore.append_to_stream(stream_uuid, 0, Commanded.Event.Mapper.map_to_event_data(initial_events, UUID.uuid4(), UUID.uuid4(), %{}))
{:ok, _handler} = AppendingEventHandler.start_link(start_from: :origin)
{:ok, 2} = EventStore.append_to_stream(stream_uuid, 1, Commanded.Event.Mapper.map_to_event_data(new_events, UUID.uuid4(), UUID.uuid4(), %{}))
wait_for_event MoneyDeposited
Wait.until(fn ->
assert AppendingEventHandler.received_events() == initial_events ++ new_events
received_metadata = AppendingEventHandler.received_metadata()
assert pluck(received_metadata, :event_number) == [1, 2]
assert pluck(received_metadata, :stream_version) == [1, 2]
Enum.each(received_metadata, fn metadata ->
assert Map.get(metadata, :stream_id) == stream_uuid
assert %NaiveDateTime{} = Map.get(metadata, :created_at)
end)
end)
end
test "should ignore already seen events" do
{:ok, handler} = AppendingEventHandler.start_link()
events = [
%BankAccountOpened{account_number: "ACC123", initial_balance: 1_000},
%MoneyDeposited{amount: 50, balance: 1_050}
]
recorded_events = EventFactory.map_to_recorded_events(events)
# send each event twice to simulate duplicate receives
Enum.each(recorded_events, fn recorded_event ->
send(handler, {:events, [recorded_event]})
send(handler, {:events, [recorded_event]})
end)
Wait.until(fn ->
assert AppendingEventHandler.received_events() == events
assert pluck(AppendingEventHandler.received_metadata(), :stream_version) == [1, 2]
end)
end
describe "event handler name" do
test "should parse string" do
assert Commanded.Event.Handler.parse_name(__MODULE__, "foo") == "foo"
end
test "should parse atom to string" do
assert Commanded.Event.Handler.parse_name(__MODULE__, :foo) == ":foo"
end
test "should parse tuple to string" do
assert Commanded.Event.Handler.parse_name(__MODULE__, {:foo, :bar}) == "{:foo, :bar}"
end
test "should error when parsing empty string" do
assert_raise RuntimeError, fn ->
Commanded.Event.Handler.parse_name(__MODULE__, "")
end
end
test "should error when parsing `nil`" do
assert_raise RuntimeError, fn ->
Commanded.Event.Handler.parse_name(__MODULE__, nil)
end
end
end
test "should ensure an event handler name is provided" do
assert_raise RuntimeError, "UnnamedEventHandler expects `:name` to be given", fn ->
Code.eval_string """
defmodule UnnamedEventHandler do
use Commanded.Event.Handler
end
"""
end
end
test "should allow using event handler module as name" do
Code.eval_string """
defmodule EventHandler do
use Commanded.Event.Handler, name: __MODULE__
end
"""
end
end