Say I have a module called MyModule with the following functions:
def get_rank(member_id) do
Account.get_user_by_id(member_id).rank
end
def get_rank_2(member_id) do
get_rank(member_id) * 2
end
I want to mock the get_rank function so it just returns 0.
So I setup my test as follows:
setup_with_mocks([
{MyModule , [:passthrough], [get_rank: fn(member_id) -> 0 end]},
]) do
:ok
end
If create these two tests, only one of them passes:
test "mock set up 1" do
assert 0 == MyModule.get_rank("test")
end
test "mock set up 2" do
assert 0 == MyModule.get_rank_2("test")
end
This means that get_rank_2
is using the real get_rank
rather than the mock. Is there a way to get it to use the mock?
Here:
setup_with_mocks([
{MyModule , [:passthrough], [get_rank: fn(member_id) -> 0 end]},
{MyModule , [:passthrough], [get_rank_2: fn(member_id) -> 0 end]},
]) do
:ok
end
Or you can just use with_mock
in each individual test which I think is the much better idea:
test "mock set up 1" do
with_mock MyModule , [:passthrough], [get_rank: fn(member_id) -> 0 end] do
assert 0 == MyModule.get_rank("test")
end
end
And you can do the same with get_rank_2
.
Thinking of it though, I am not sure what does :passthrough
even do. Why would it “pass through arguments to the original module” if you are mocking it and the original module’s function will never be hit?
Strange.
Mocking a call without the module specifier (like get_rank
in get_rank_2
) is explicitly NOT supported by Mock:
It is important to understand that only fully qualified function calls get mocked. The reason for this is because of the way Meck is structured. Meck creates a thin wrapper module with the name of the mocked module (and passes through any calls to the original Module in case passthrough is used). The original module is renamed, but otherwise unmodified. Once the call enters the original module, the local function call jumps stay in the module.
1 Like
I still don’t get the idea of passthrough; why would you call the original module at all? You’re mocking it add shouldn’t be interested in it after all, no?
I’ve only used Mock a little bit quite a while ago, but my interpretation of the docs for :passthrough
is that it’s intended for situations where SomeModule
defines multiple functions but only one should be replaced with a mock.
For instance, it would be useful if you wanted to mock only DateTime.now
without also defining mocks for every call to Datetime.to_string
etc.
1 Like
While that makes sense I still can’t quite imagine it with concrete code. Would you give an example?