ream88

ream88

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?

First 4 of 4 Posts Switch mode

stefanchrobot

stefanchrobot

Why not keep it simple and use a function?

def assert_event(%event_mod{} = event, func) do
  pid = spawn(fn ->
    EventStore.subscribe(event_mod)
    assert_receive ^event
    EventStore.acknowledge(event)
  end)

  ref = Process.monitor(pid)

  func.()

  assert_receive {:DOWN, ^ref, _, _, _}
end
ream88

ream88 OP

Yeah, a function would have been sufficient, I think I just got carried away with the nicer syntax with a do block instead of an inline func (sorry, still a lot of Ruby influences here :wink:). However the problem still persists. I cannot forward the match to the function. The problem is, I need to work with a match here, as I don’t know all the data inside the emitted event, and therefore can’t use a simple == comparison.

LostKobrakai

LostKobrakai

Pattern matches are a compile time structure in code. You cannot „pass“ a pattern at runtime, so the only way to do it is using macros. When using macros you‘ll need to read up on macro hygine, so variables within generated code become accessible to code not being generated.

ream88

ream88 OP

Yeah, that’s probably the topic I will have to deep dive into :blush: Thx a lot!

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement