Open slashdotdash opened 4 years ago
Commanded Ecto projectors are regular Commanded.Event.Handler
s under the hood.
Recipe #15 explains how event handlers can be tested, and includes the following example:
# Or call handler directly with an event (doesn’t require the handler process to be started) :ok = CustomerPromotionHandler.handle(event, metadata)
Which shows that event handlers can be tested by calling the
handle/2
callback directly. Rather than dispatching an event.
Now take one of the examples in the commanded-ecto-projection
documentation. We could do the following in tests:
metadata = %{
event_number: 1,
handler_name: "fake-handler-name"
}
:ok = MyApp.ExampleProjector.handle(event, metadata)
So we can test Commanded Ecto projections directly by calling the handle/2
function on the projector. There is no need to depend on command dispatches, nor telemetry events to wait and acknowledge that the projector was called. We can simply build an event, call the projector, and that's about it.
@slashdotdash Wdyt? Would this be a recommended approach?
How can I test a read model projector so that tests wait until events have been projected?
Using Elixir telemetry and the
after_update/3
callback functionCommanded Ecto projections provides an
after_update/3
callback function. This gets called after each event is projected. You can use the funtion to publish a notification whenever an event is projected, including the database changes.Here’s an example using the Elixir/Erlang telemetry library.
In the projector:
In a test:
Usage in test to wait:
This approach will ensure the test blocks until the projector has done its work and then you can run either use the changes from the Ecto.Multi or run a query to verify the database changes. You can also use pattern matching on the event from the telemetry metadata to wait for a particular event type.
The performance impact at runtime is negligible if there are no handlers attached to a telemetry event.