Hey,
I’m currently trying to DRY up some tests which have a lot of boilerplate code in the form of:
test "user is updated", %{user_id: user_id} do
pid = spawn(fn ->
EventStore.subscribe(UserUpdated)
assert_receive event = %UserUpdated{aggregate_id: ^user_id}
EventStore.acknowledge(event)
end)
ref = Process.monitor(pid)
# the actual test
assert_receive {:DOWN, ^ref, _, _, _}
end
Basically I’m checking if the event UserUpdated
is fired in our custom event_store. I tried to implement a custom macro like this:
defmacro assert_event(event, do: block) do
quote do
pid =
spawn(fn ->
EventStore.subscribe(unquote(event).__struct__)
assert_receive event = unquote(event)
EventStore.acknowledge(event)
end)
ref = Process.monitor(pid)
unquote(block)
assert_receive {:DOWN, ^ref, _, _, _}
end
end
Which can then be used like this:
test "user is updated", %{user_id: user_id} do
assert_event %UserUpdated{aggregate_id: user_id} do
# the actual test
end
end
But this results in the following warning:
warning: variable “user_id” is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)
But pinning user_id results in the following error:
cannot use ^user_id outside of match clauses
So, my question is (after reading the complicated source code of assert_receive
), is there a way to mark some code as a pattern and just forward it to the assert_receive
macro inside my custom assert_event
macro?