Load all files from a directory and get the modules in those files

Hi,

I am using mocking in my unit tests in my code. My mocks are however, injected through Application config,
For example, if Application.get_env(:app, :httpclient) is HTTPoison in my development and production, it would be a special dummy module called HTTPoisionMock I created for testing purposes. This module has exactly the same API as HTTPoison but it’s function calls can be mocked.

Now, at the beginning of my test run, I need to initialize these mocks, meaning, I need to call a init() function on each of them so that they are “registered”.

I would like to see if there is a way for the for the test_helper.exs to automatically get all the modules from test/mocks/ directory and call .init() on each of them?

currently I am manually maintaining a list of these modules and doing init in the following way:

mocks = 
 [ 
  Mocks.MailerMock,
  Mocks.AccountsMock,
  Mocks.HTTPoisonMock,
]
Enum.each mocks, fn(m)->
  m.init()
end

I would like to get rid of all this manual maintenance and let the code do it.
Any help would be appreciated, thank you!

You can use File.ls/1 to read the directory.

If then you have a proper naming schema that you can map programmatically from filename to module name, then apply it and initialise them. Macro.camelize/1 might be helpful.

There is no such function per default, as there is nothing that forces you to actually have a relationship between filename and defined modules.

If all modules you are using have common prefix then you can use :code.all_loaded() and filter modules that match given prefix. Alternatively you can just list all mocked variables in Application.config and use that, either via Application.get_env or via Application.get_all_env.

However I would avoid global mocks if you can, especially when these mocks have global state (I assume that they have as you need globally call init/0 on them).

1 Like

Thank you, I ended up doing this, constructing module names based on their path.
Seems to have worked well.