How do I test things like IO, File, and System?

My aspirational goal is to get 100% of my Elixir code tested with unit tests alone. Code not run by the Erlang runtime system, such as SQL database queries, while certainly side effecting, is not Elixir code so I am fine with using integration tests for those as long as all of the Elixir code used to transmit the SQL to the database is unit tested.

In this sense, I believe my sample using dependency inversion did achieve 100% pure code with no side effects for every single bit of my Elixir logic, in a way that can be generalized to any kind of side effects. The only class that did not have test coverage was the class that configured which production implementations to use, which is fine by me because that configuration contains no application behavior, just direct pass throughs to the underlying implementations. It is so simple it it could be generated. All of the application behavior is easy to stub out for unit tests, no need for integration tests for Elixir code and no need to skip test coverage on anything.

That said, I am also willing to be pragmatic about my aspirational goal, and am willing to pull back on it in cases where there is good reason and a decent alternative. I don’t want to be writing Elixir code in a style completely alien to the rest of the Elixir community just for the sake of principle.

I am also willing to explore alternative suggestions that can get me close to my aspirational goal through means I might not be able to think of on my own due to my inexperience with Elixir. This is why I am grateful for the suggestions to look into Mox, Ecto, and jjh42/mock. I might have missed these on my own. Once I have had a chance to review all of the solutions, I feel like I can make an informed decision regarding what tradeoffs between functional purity and pragmatism are sensible. I don’t want to presume I have to make a tradeoff, I want to make sure any tradeoffs I make are for well understood and good reasons.