Correctly testing and mocking a GenServer that performs initialisation on start

Hi all,

I have a simple GenServer that performs some initialisation on start. That initialisation process involves making some calls to an HTTP API. I have delegated the HTTP communications to a lower level module, which I then mock using Mox. All well and good.

The GenServer is in my supervision tree in a vanilla sort of way so it gets started every time I run mix test. That would be fine except the GenServer starts making calls to my mock before I’ve had a chance to specify what the response should be, and mox raises a Mox.UnexpectedCallError.

So my question is; what’s the most idiomatic way of testing this? Options I’ve considered:

  • Preventing applications from being manually started by using mix test --no-start and then manually starting the pieces I need. This is fine but the auto-start behaviour is working nicely elsewhere so would add more work.
  • Selectively changing which processes are started depending on environment. Again this works fine.

Something tells me there is a better way. Thanks for any help!

I would have a default mock in the test.exs config and let this genserver make useless calls. And to actually test the genserver I would call its functions in my test directly, not relying on the actual process that is started in the supervision tree.

That’s pretty much as far as I’ve got but since that default mock hasn’t been configured with any expectations yet I get the Mox.UnexpectedCallError situation.

How do you specify your default mock?

I don’t know as I have never used a mocking library in elixir yet. If you genserver receives a module then you can implement a NoopHttpClient module maybe.

As @lud suggested I’ve ended up creating a “default mock” in the form of a stub.

I followed the instructions laid out here: https://nts.strzibny.name/elixir-mocking-mox/

2 Likes