AndyL
GenServers - how to test with `capture_io`?
I’ve got a Genserver that writes messages to stdout. I can’t figure out how to test using capture_io. Documentation says By default, capture_io replaces the group_leader (:stdio) for the current process. Perhaps there is a Process.group_leader call that will make this work, but I haven’t been able to find it. Can anyone point me to a solution?
Here’s a failing test script…
#!/usr/bin/env elixir
ExUnit.start()
defmodule MyGenServer do
use GenServer
def start_link(default \\ []) do
GenServer.start_link(__MODULE__, default, name: __MODULE__)
end
def init(initial_state) do
{:ok, initial_state}
end
def handle_call(:sayhi, _caller, state) do
IO.puts("HI")
{:reply, :ok, state}
end
end
defmodule MyGenServerTest do
use ExUnit.Case
import ExUnit.CaptureIO
test "GenServer responds to :sayhi call by writing 'HI' to stdout" do
{:ok, pid} = MyGenServer.start_link()
assert capture_io(fn -> GenServer.call(pid, :sayhi) end) == "HI\n"
end
end
Marked As Solved
voughtdq
The problem is that you have to set the group leader first, which doesn’t seem possible with the way that capture_io/1 currently works:
# group leader is set before starting the GenServer, so this works
assert ExUnit.CaptureIO.capture_io(fn ->
{:ok, pid} = MyGenServer.start_link()
GenServer.call(pid, :sayhi)
GenServer.stop(pid)
end) == "HI\n"
I wonder what the ideal way to do this would be. If we had some way of telling capture_io to use the pid of the GenServer, then it could properly set the group leader.
Maybe something like this:
{:ok, pid} = MyGenServer.start_link()
assert ExUnit.CaptureIO.capture_io([pid: pid], fn -> GenServer.call(pid, :sayhi) end)
Also Liked
voughtdq
Just a heads up that this will now be possible in v1.17.0:
assert ExUnit.CaptureIO.capture_io(pid, fn ->
GenServer.call(pid, :sayhi)
end)
AndyL
ityonemo
if you can’t wait for elixir 1.17, you can manually set the group_leader of the pid you want using :erlang.group_leader/2 to your test process and assert_receive on the messages that flow in.
Be careful! The order of the parameters on :erlang.group_leader/2 might not be the order you expect.
Last Post!
ityonemo
if you can’t wait for elixir 1.17, you can manually set the group_leader of the pid you want using :erlang.group_leader/2 to your test process and assert_receive on the messages that flow in.
Be careful! The order of the parameters on :erlang.group_leader/2 might not be the order you expect.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









