Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eunit test process dies on purge of meck module #61

Closed
bjnortier opened this issue Mar 26, 2012 · 7 comments
Closed

Eunit test process dies on purge of meck module #61

bjnortier opened this issue Mar 26, 2012 · 7 comments

Comments

@bjnortier
Copy link
Contributor

I have an issue with some Eunit tests that don't run because of the code:purge/1 step when unloading a module. I've recreated the problem below and it's also available at https://github.com/bjnortier/meck-issue

When I run the eunit tests with rebar the test process terminates:

$ rebar -v skip_deps=true compile eunit
==> meck-issue (compile)
==> meck-issue (eunit)
======================== EUnit ========================
a:8: a_test_ (module 'a')...ok
module 'b'
  b:16: b_test_...ok
undefined
*unexpected termination of test process*
::killed

Failed: 0. Skipped: 0. Passed: 2.
One or more tests were cancelled.
ERROR: One or more eunit tests failed.

Which I have traced to the code:purge/1 function when unloading a module. I suspect it's because of the following bit in the docs for code:purge/1:
"If some processes still linger in the old code, these processes are killed before the code is removed."

Module a is tested first, which loads the real a. Then the tests for module b mocks/mecks module a, which is already loaded. So ordering is important.

Perhaps someone with more knowledge of code loading/unloading can help.
Here are the two modules:

-module(a).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").

a_test_() ->
    [
     ?_assert(true)
    ].

-endif.


-module(b).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").

b_test_() ->
    {setup,
     fun() ->
             ok = meck:new(a)
     end,
     fun(_) -> 
             meck:unload(a)
     end,
     fun(_) ->
             [
              ?_assert(true)
             ]
         end
    }.

-endif.
@eproxus
Copy link
Owner

eproxus commented Mar 28, 2012

Why are you trying to mock another test module?

I know that EUnit has a quite weird process model and have encountered similar errors in the past. I think that you shouldn't rely on mocking other test modules that might be in use by EUnit.

@bjnortier
Copy link
Contributor Author

In this specific case, module a is a gen_server with complex initialisation behaviour (i.e. spawning linked processes etc.) that I would like to avoid, but essentially I should be able to mock anything I would like.

If it's a limitation of meck that other modules being tested cannot be mocked, then I will accept it as such and make another plan.

@eproxus
Copy link
Owner

eproxus commented Mar 28, 2012

Are the tests located inside the gen_server module itself?

@bjnortier
Copy link
Contributor Author

Yes. Would moving them to a separate test module help?

@eproxus
Copy link
Owner

eproxus commented Mar 28, 2012

Most likely. That way you would avoid reloading the test module that EUnit uses. In my opinion that is a good practice anyhow.

Another good practice would be to separate out the complex behavior into a separate module and mock that. When you test your main module, it can get very tricky when you mock it at the same time (you actually modify the code under test with Meck, so you can't really be sure that it works since it is not really the original code).

@bjnortier
Copy link
Contributor Author

Ok I'll do that and close the issue.

@eproxus
Copy link
Owner

eproxus commented Mar 28, 2012

Just re-open it if it doesn't solve the problem! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants