Asserting IO.puts output which is NOT the return value of the function

I have the following code:

def my_func() do
  IO.puts("Hello, Elixir!")
  :init_state
end

In my tests, I want to assert the string being output by the IO.puts.
I know about capture_io, but since the string is not the return value of the function, trying assert capture_io(&my_func/0) == "Hello, Elixir!") fails (since I’m using the excellent PowerAssert library I can also tell it fails because the assertion value is the empty string "").

For the purpose of this question, I must not separate the two actions into two separate functions and I must return the atom.

Is there a way to assert the output while still returning the atom?

Works for me:

ExUnit.CaptureIO.capture_io(fn -> IO.puts("foo"); :foo end) == "foo\n"
#=> true

Remember though, that IO.puts/1 adds a newline, so assert capture_io(&my_func/0) == "Hello, Elixir!\n" should work for you.

4 Likes