Closed fcristovao closed 4 years ago
Feels like it would benefit from sharing part of implementation with unload_if_mocked
or unload/0
I thought the same, but I wanted to prevent doing 2 passes over a (sub)list.
If that would be ok, I think that unload
could just call mocked()
instead of registered()
.
❤️
If you are up for it, I would suggest some refactoring that allows us to re-use code in all scenarios:
for_each_mock/1
function that looks approximately like your existing loop:
for_each_mock(Fun) ->
lists:foldl(fun(M, Acc) ->
case lists:suffix("_meck", atom_to_list(M)) of
true ->
case Fun(M) of
{ok, Elem} -> [Elem|Acc];
skip -> Acc
end;
false ->
ok
end
end, [], erlang:registered()).
mocked/0
like so:
mocked() -> for_each_mock(fun(M) -> {ok, M} end).
unload/0
like so:
unload() ->
for_each_mock(fun(M) ->
try
unload(M),
{ok, M}
catch
error:{not_mocked, M} -> skip
end
end).
This should keep the existing behaviour and then we can delete the old unload_if_mocked
function. This version also only makes one pass over the names list. Thoughts?
I really like the idea!
However, It honestly feels like this is more like a "filterfoldl".
That way, unload
and mocked
would just be regular foldl funs, albeit only applied to modules we know are mocked.
I'll do the changes tonight and submit it :)
Or fold_mocks(fun(MockName, Acc) -> <...>, NewAcc end, InitialAcc)
- this one should be more flexible since fun
is responsible for accumulator
fold_mocks(fun F/2, InitialAcc)
looks nice! 👍
I've updated the PR.
I've left the way to find out which mocks are mocked as the way I had. The given suggestion (with the lists:reverse
), would still require a split somehow to find the original name. This way, in one operation we get the original name of the mocked modules.
And all used functions are available in OTP 18 onwards, as requested.
@fcristovao Sorry, I did a later edit to lists:suffix("_meck", atom_to_list(M))
which I think is the cleanest, most compatible solution. Mind updating it?
Never mind, missed that you need the original module name, not the mock name! 🤦
However, I think you don't need your old expression since all modules are guaranteed to have the _meck
suffix when the fun is called. You can just created the original name from the module name (might I suggest a new function in meck_util
for this?).
@eproxus Is your suggestion that the "foldl" functions should get the name of the modules in <original>_meck
form instead of <original>
? I can do that, but I don't really see the benefit of that part (as both functions would then still need to get the original module name anyway)?
The foldl_mocks
function still needs to filter, as its source is the registered()
call instead.
Thanks, great work! I really like the test as well!
There's already an
meck:expects/[1,2]
, allowing introspection into what kind of expectations are set. This allows one to also check which modules is meck handling at any point.