Just another idea, following @josevalim rationally and with no external dependencies. Code isn’t readable since Erlang trace API is complicated. But if you abstract the complication away in test helper functions, it can become manageable…
pattern = {Module, :function, 0} # it can be any {mod, fun, arity}
:erlang.trace_pattern(pattern, [{:_, [], [{:return_trace}]}])
:erlang.trace(:all, true, [:call])
# do async work that ends up calling Module.function()
assert_receive {:trace, _pid, :return_from, ^pattern, {:noreply, _state}} # block until Module.function is called
# write the rest of your assertions here, the ones that need `Module.function` to be returned...






















