Mock
depends on :meck
, which does swap out the complete module within the runtime – as in make the VM unload the existing module and load the module with the mock code. That architecture cannot support concurrent tests. The best improvement to get would be better errors or disclaimers.
What you call an issue is imo a good driver for well rounded mocking.
There’s the guideline of “don’t mock what you don’t own”. You don’t own the API of File
– the core team does. Elixir does well with not doing backwards incompatible changes, but they could always add new return values and such. You might not become aware of those additional return values, so you won’t be testing for those, which might break your code in production while even well setup tests – working on an incomplete assumption of the interface – would suggest everything is fine.
Instead you want to create your own interface (in the form of a behaviour), around the actual usecases you have for interacting with the filesystem. Let’s call it MyApp.FileStorage
. Then you own the interface between your code and the underlying implementation using File
’s API (MyApp.FileStorage.LocalFiles
), as well as the implementation you use in tests (MyApp.FileStorage.Mock
).
Changes in File
’s APIs then no longer affect your mocked interface MyApp.FileStorage
. They only affect the implementation MyApp.FileStorage.LocalFiles
, which you hopefully tested separately without mocks to ensure it works correctly. Those tests hopefully fail before you push to production. All tests using the mock implementation would be unaffected.
One sideeffect of that approach is also that your interface might becomes smaller. Instead of the whole File
API you’ll likely shrink the mocked interface to a few more select things your codebase actually needs, potentially even shrinking the number of possible parameters and return values as well. Complex tasks, which require multiple calls to File
API might become a single callback on your behaviour, again simplifying the interface and how much work it would be to mock.