Fl4m3Ph03n1x
--breakpoint flag changes the behaviour of mix test using bypass
Background
I am trying to do an integration test for a simple terminal application that I am writting.
This application is basically a Supervisor, which supervises other smaller libraries.
The communication within the project is mostly asynchronous, with processes sending messages to callers.
Problem
One of the tests I make requires an HTTP request, so I decided to use bypass for this. However, the problem is rather surprising to me. Here is the test:
setup do
bypass = Bypass.open(port: 8082)
credentials = %{email: "an_email", pass: "a_password"}
%{
credentials: credentials,
bypass: bypass
}
end
test "logs in user correctly", %{bypass: bypass, credentials: credentials} do
Bypass.expect_once(bypass, fn conn ->
IO.inspect(conn.request_path, label: "REQ PATH")
IO.inspect(conn.method, label: "METHOD")
Plug.Conn.resp(conn, 429, ~s<{"errors": [{"code": 88, "message": "Rate limit exceeded"}]}>)
end)
# start the application
_manager_pid = start_link_supervised!(ManagerSupervisor)
# this should make a GET request to bypass but ...
Manager.login(credentials, false)
end
If I simply run mix test this simple test fails as Bypass received no requests.
1) test login logs in user correctly (Manager.WorkerTest)
test/integration/manager_test.exs:83
No HTTP request arrived at Bypass
Confusion
However, confunsingly enough, if I use the --breakpoints feature by running iex -S mix test --breakpoints I can make the test pass by doing some simple steps:
- Press
nline by line. - When reaching the last line (
Manager.login(credentials, false), I do not execute it withnorc. Instead I manually type the commandManager.login(credentials, false). - The call to
bypassis made - Then I press
cand the test passes
This is beyond confusing to me. It appears that the test process in not invoking Manager.login like it should.
I cannot explain this.
Questions
- Why is the
bypassbeing called when I invokeManager.loginmanually using the--breakpointoption and not whenmix testruns? - How can I fix my test?
Marked As Solved
RudManusachi
Is it possible that when ran without breakpoints the test finishes before the process makes the call. While with breakpoints, by the time you press c, Manage.login/2 makes its way to send the message?
I’d try to synchronize the test and Bypass with something like:
test "logs in user correctly", %{bypass: bypass, credentials: credentials} do
test_pid = self()
Bypass.expect_once(bypass, fn conn ->
IO.inspect(conn.request_path, label: "REQ PATH")
IO.inspect(conn.method, label: "METHOD")
send(test_pid, :logging_in)
Plug.Conn.resp(conn, 429, ~s<{"errors": [{"code": 88, "message": "Rate limit exceeded"}]}>)
end)
_manager_pid = start_link_supervised!(ManagerSupervisor)
Manager.login(credentials, false)
# this ensures that the test will not exit until the message is received
# (or until the default `assert_receive` timeout 100ms)
assert_receive :logging_in
end








