Skip to content

Commit 84abb39

Browse files
authored
Add a very simple wrapper (in_series) around :meck.seq (#132)
1 parent c630587 commit 84abb39

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ See the full [reference documentation](https://hexdocs.pm/mock/Mock.html).
1818
* [*setup_with_mocks* - Configure all tests to have the same mocks](#setup_with_mocks---Configure-all-tests-to-have-the-same-mocks)
1919
* [Mocking input dependent output](#Mocking-input-dependent-output)
2020
* [Mocking functions with different arities](#Mocking-functions-with-different-arities)
21+
* [Mocking repeated calls to the same function with different results](#Mocking-repeated-calls-to-the-same-function)
2122
* [*passthrough* - partial mocking of a module](#passthrough---partial-mocking-of-a-module)
2223
* [Assert called - assert a specific function was called](#Assert-called---assert-a-specific-function-was-called)
2324
* [Assert called - specific value](#Assert-called---specific-value)
@@ -204,7 +205,7 @@ defmodule MyTest do
204205
assert Map.get(%{}, "http://example.tech") == "<html>example.tech says hi</html>"
205206
end
206207
end
207-
208+
208209
def conditionally_mocked(url) do
209210
cond do
210211
String.contains?(url, ".xyz") -> "<html>Hello from example.xyz</html>"
@@ -237,6 +238,35 @@ end
237238

238239
````
239240

241+
## Mock repeated calls
242+
243+
You can mock repeated calls to the same function _and_ arguments to return
244+
different results in a series using the `in_series` call with static values.
245+
This does not currently support _functions_.
246+
247+
**Caution**: This is only useful in rare instances where the underlying business
248+
logic is likely to be stateful. If you can avoid it by using different function
249+
arguments, or refactor the function to be stateful, consider that approach first.
250+
251+
```` elixir
252+
defmodule MyTest do
253+
use ExUnit.Case, async: false
254+
255+
import Mock
256+
257+
test "mock repeated calls with in_series" do
258+
with_mock String,
259+
[slice: [in_series(["test", 1..3], ["string1", "string2", "string3"])]]
260+
do
261+
assert String.slice("test", 1..3) == "string1"
262+
assert String.slice("test", 1..3) == "string2"
263+
assert String.slice("test", 1..3) == "string3"
264+
end
265+
end
266+
end
267+
268+
````
269+
240270
## *passthrough* - partial mocking of a module
241271

242272
By default, only the functions being mocked can be accessed from within the test.

lib/mock.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,4 +366,8 @@ defmodule Mock do
366366
:meck.expect(mock_module, fn_name, value)
367367
_install_mock(mock_module, tail)
368368
end
369+
370+
def in_series(signature, results) do
371+
{signature, :meck.seq(results)}
372+
end
369373
end

test/mock_test.exs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,21 @@ defmodule MockTest do
6464
assert result == 6
6565
end
6666

67+
test "mock returns multiples results in sequence" do
68+
with_mock String, [
69+
reverse: [in_series([:_], [:a, :b, :c])],
70+
slice: [in_series([1, 2], [:x, :y, :z])]
71+
] do
72+
assert String.reverse(1) == :a
73+
assert String.reverse(1) == :b
74+
assert String.reverse(1) == :c
75+
76+
assert String.slice(1, 2) == :x
77+
assert String.slice(1, 2) == :y
78+
assert String.slice(1, 2) == :z
79+
end
80+
end
81+
6782
test "called" do
6883
with_mock String,
6984
[reverse: fn(x) -> 2*x end,

0 commit comments

Comments
 (0)