alex88
I’m trying to mock ExTwitter during tests, I’m using GitHub - dashbitco/mox: Mocks and explicit contracts in Elixir · GitHub for that.
In my code I use a config variable to do the Dependency Injection, like this:
config :my_app,
# DI
twitter_client: MyApp.TwitterClient
I’ve defined my mock in test/support/mocks.ex as per Mox docs like this
Mox.defmock(MyApp.Mocks.TwitterClient, for: MyApp.TwitterClient)
and in my test.exs config I have
config :my_app,
# DI
twitter_client: MyApp.Mocks.TwitterClient
Everything worked while incrementally compiling during development, however on a fresh checkout without any _build folder i get this error:
== Compilation error in file test/support/mocks.ex ==
** (ArgumentError) module MyApp.TwitterClient is not available, please pass an existing module to :for
lib/mox.ex:92: Mox.validate_behaviour!/1
lib/mox.ex:84: Mox.defmock/2
(elixir) lib/kernel/parallel_compiler.ex:121: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1
if I remove that mock line, compile and add the line back everything works. It seems like it’s trying to compile the mock file first and then the lib folder.
My elixirc_paths is ["lib", "test/support", "test/factories"] so lib comes first, any idea?
I’ve pushed a sample app with the problem in https://github.com/alex88/myapp just run mix test
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #ai
- #iex
- #graphql
- #elixirconf-us
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
ericmj
The Mox documentation suggests putting the
Mox.defmockcalls intest/test_helper.exs, that’s because the test helper is evaluated after all files are compiled. When you put the calls in the body of a compiled file it will try to check the mocked module is available at compile time which is a race condition.hubertlepicki
This is actually incorrect, and also something you probably don’t want to do as you will lose compile-time compatability check of behaviors.
The problem is slightly different - i.e. the behavior is not properly specified here. I will publish a pull request for your repo @alex88 in a few mins to show you.
alex88
That’s because there is no order in the compilation process?
Anyway, having the mocked module in the test config, when I move the mock into
test_helpergenerates:so as per Mox — Mox v1.2.0 I moved the mock code into
support/mocks.exto solve that I could this in my test helper:
but is that the correct way?
hubertlepicki
hold on I’m investigating, some voodoo is going on here
alex88
Sure, just wanted to share all I tried at this point
ericmj
Yes, modules will be compiled in the correct based on the calls or requires that is made in compile time. If you call a module at compile time the calling module will wait until the callee is compiled.
If it’s supposed to be supported to define behaviour implementations* at compile time then I think this line mox/lib/mox.ex at main · dashbitco/mox · GitHub should call
Code.ensure_compiled?instead.hubertlepicki
It’s not supposed to define new behaviours at compile time. Rather that it should create behaviour-compatible mocks based on already compiled modules, but you are right, it should be
Code.ensure_compield?ericmj
If you call
Mox.defmockat compile time, which you do if you put it in the body of a file covered byelixirc_paths, then the function will callCode.ensure_loaded?at compile time. You will see that if you follow the stacktrace leading up to mox/lib/mox.ex at main · dashbitco/mox · GitHub. CallingCode.ensure_loaded?at compile is not safe because it’s a race to check if the module is loaded. If you instead callCode.ensure_compiled?then the compiler will wait until the given module is compiled, it works similar torequire. You will notice that it works if you add a call toCode.ensure_compiled?before the call toMox.defmock.hubertlepicki
Yes, you are right ref the cause of the issue.
alex88
I can confirm that changing from
Code.ensure_loaded?toCode.ensure_compiled?fixes the issue while compiling and the app tests passes