In testing with Elixir, can the dB connection assigned to a GenServer be reassigned to the testing one? - testing

My system has an app under an umbrella which starts up several GenServers, which on init make some dB calls, and thus get their own connection.
The problem is that in my tests of a controller where I have inserted some records into the dB, the controller makes a call to one of those GenServers, which then does some more dB queries. But since it is a different sandbox, it does not see the records.
I am looking for a solution in general that would allow existing, running GenServers to use the same sandbox as the test. I would greatly appreciate any ideas. I tried adding the following right after the sandbox checkout in the test setup, but didn't help:
Ecto.Adapters.SQL.Sandbox.allow(MyApp.Repo, self(), Some.GenServer)

The only working solution I found was to allow the GenServer to be started with an alternate name, starting it up thus using the same sandbox db connection as the test, having my controller use this differently named version, and shutting it down right before the end of the test.

Seems that I ended up with the same issue.
My solution was to keep the default Phoenix settings, and terminate and restart my process before each test, like this:
setup(%{conn: conn}) do
Supervisor.terminate_child(Some.Supervisor, Some.GenServer)
Supervisor.restart_child(Some.Supervisor, Some.GenServer)
{:ok, conn: conn}
end
Tests SHOULD NOT be async: true

Related

How to check the contents of postgres

I'm running tests with Matchstick and my save() calls don't seem to be working (I set up my tests by saving some entities, but then my application code doesn't see them when it goes to load).
Is there any way to check the current state of the backend and see what's in there? Mainly just trying to troubleshoot.
Turns out, you just have to read the docs
https://thegraph.com/docs/en/developer/matchstick/
logStore()

Mock a client to a dependency when doing integration tests

I have a service composed of several micro services working in workflow. Some of these MS are calling dependencies.
Now I'd like to mock these calls, so when I send a message at the entrance of the workflow the dependencies answers get mocked, but my system works as normal.
The challenge is that I would want to configure the mock from the outside: Configure on the fly the answer I want to get from the mock, run my test, verify that my system behaves properly.
I worked for a company that shall remain unnamed that has an internal tool doing just that, but I'm wondering if there is a public tool doing this? I can't believe it doesn't exist, I bet more on my lack of knowledge about this, at that point ;)
Cheers
So far best I've found is https://wiremock.org/docs/
I don't want to do any ad here, it's just the only one I see that gets its mocks configured from a distance

Is there a way to simulate the lack of internet connection in an Elixir test?

I am dealing with a coverage test of an command-line interface application developed in Elixir. The application is a client for tldr-pages and its functioning consists in a script built with escript. To perform the actions I use a case structure over an HTTPoison.get/1 function, in which I introduce the formatted url. In this case I compare the response to different kind of values, such as if the page exists, it shows the information; if the not, it report it to the user and then continue in another case to evaluate to others possibilities. At the end, the first case finish with two pattern to match errors, one for the lack of internet connection and another one for unexpected errors. The described structure is the next one:
case HTTPoison.get(process_url(os, term)) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
IO.puts(body)
{:ok, %HTTPoison.Response{status_code: 404}} ->
IO.puts(
"Term \"#{term}\" not found on \"#{os}\" pages\nExTldr is looking on \"common\" pages."
)
case HTTPoison.get(process_url("common", term)) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
IO.puts(body)
{:ok, %HTTPoison.Response{status_code: 404}} ->
IO.puts("Term not found on \"common\" pages.")
end
{:error, %HTTPoison.Error{reason: reason}} when reason == :nxdomain ->
raise NoInternetConnectionError
{:error, %HTTPoison.Error{reason: reason}} when reason != :nxdomain ->
raise UnexpectedError, reason
end
NoInternetConnectionError and UnexpectedError are exceptions defined in another file. Both patterns at the end works apparently nice, at least the first one:
{:error, %HTTPoison.Error{reason: reason}} when reason == :nxdomain ->
raise NoInternetConnectionError
However, as I said at the beginning of the question, I am dealing with a coverage test performed automatically with GitHub Actions and Coveralls with ExCoveralls in the dependencies. In this test I am receiving a warning for both raise/1 statements. Although I could be wrong understanding what means that, I understand this "missed lines" or uncovered lines are reported by Coveralls because I am not performing a test to cover this case. Thus I started to research how I could write a test to cover both conditions.
The most important issue is how to simulate the lack of internet connection in a test to cover this. I though about to develop a mock, but I do not find something useful for this case in some of the mocking packages for Elixir, like Mox. Then I found bypass, a very interesting package that I think it might be useful because it has down/1 and up/1 to close and start a TCP socket, so it makes possible to test what happens when HTTP server is down. But with this I have two issues:
A server down is not the same that the lack of internet connection by the user part.
I tried to applied this "down and up" mechanism and I did not accomplish it. I am not going to share it because I think it would not be the final solution by the first issue described.
I am not pretending an answer with the code that solves this problem, I am just trying to understand how this test should work and the logic I should follow to develop it. I am even researching Erlang documentation, because it is possible Erlang provides native functions to address it (for example, I am now reading the Erlang's Common Test Reference Manual, because may be there is something useful there).
Edit. What I commented I tried with bypass was to install the dependency, write a setup with bypass.open/0 and then write a test like the next one, in which I try to assert the capture output with capture_io/1:
test "lack of internet connection", %{bypass: bypass} do
Bypass.down(bypass)
execute_main = fn ->
ExTldr.main([])
end
assert capture_io(execute_main) =~ "There is not internet connection"
end
However, as I thought, it does not cover the possible situation of lack of internet, just the possibility to check when a server goes down.
Sidenote: I personally was always against being a slave of tools that are supposed to help the development. Coverage is a somewhat good metric, but the recommendations should not be treated as a must. Anyway.
I am not sure why you ruled Mox out. The rule of thumb would be: tests should not involve cross-boundary calls unless absolutely unavoidable. The tests going over the internet are nevertheless flaky: coverage would not tell you that, I would. What if the testing environment has no permanent internet access at all? Temporary connection issues? The remote is down?
So that is exactly why Mox was born. And, luckily enough, HTTPoison is perfectly ready to use Mox as a mocking library because it declares a behaviour for the main operation module, HTTPoison.Base.
All you need would be to make your actual HTTP client an injected dependency. Somewhat along these lines:
#http_client Application.get_env(:my_app, :http_client, HTTPoison)
...
case #http_client.get(process_url(os, term)) do
...
end
In config/test.exs you specify your own :http_client, and voilà—the nifty mocked testing environment is all yours.
Or, you might declare the mock straight ahead:
Mox.defmock(MyApp.HC, for: HTTPoison.Base)
I am also adept of boundaries on the application level calling 3rd-parties. That said, you might define your own behaviour for external HTTP calls you need and your own wrapper implementing this behaviour. That way mocking would be even easier, and you’ll get a benefit of easy changing the real client. HTTPoison is far from being the best client nowadays (it barely supports HTTP2 etc,) and tomorrow you might decide to switch to, say, Mint. It would be drastically easier to accomplish if all the code would be located in the wrapper.

When testing end to end integration testing using TestCafe how to manage waiting for email receipt

With system under test, when adding a new user their initial password is emailed to them.
I could split my test into multiple sections with manual intervention but this is less than ideal.
Appreciate any suggestions on how to proceed using TestCafe as I am sure others have encountered this as well.
If you run full integration test with real email server, then you can use libraries like "mail-receive" to connect to this server and verify the email.
You can also run your backend/server logic in mock mode, and then verify the mock, that the send event happened, by calling some test-specific rest endpoint from your TestCafe test.
Alternatively, you could also use something like "smtp-receiver" to start your own email-server-mock in nodejs context, and receive event upon email arrival. However you will need to configure your app server/backend to point to this mocked email server.

Remote debug Idea doesn't works for openresty

I am using mobDebug. If run a lua script from command line everything works.
But when I run them from openresty the Idea doesn't stop. It only writes "Connected/ Disconnected"
Configs:
location / {
access_by_lua_block {
local client = require("client")
}
client.lua:
local mobdebug = require("mobdebug");
mobdebug.start()
local lfs = require("lfs")
print("Folder: "..lfs.currentdir())
modebug debug_hook is not invoked for needed lines, set_breakpoints don't invoked.
Idea Debug Logs, but nothing occures:
Idea catch debug from terminal client.lua; But it miss it from running nginx.
THIS IS NOT AN ANSWER. It's just that I am experiencing basically the same problem, and comment space is too small to fit all the relevant observations I would like to share:
I was actually able to stop immediately after mobdebug.start() in code running in nginx, and to step-debug - but only in code called directly from init_by_lua_block. This code of course executes once during the server startup or config reload.
I was never able to stop in worker code (e.g. rewrite_by_lua_*). mobdebug.coro() didn't help, and mobdebug.on() threw about "attempt to yield across C-call boundary"
I was only ever able to stop one time, on next statement after mobdebug.start(); once I hit |> (Resume program), it won't stop on any further breakpoints.
Using mobdebug.loop() is not a correct way to do this, as it's used for live coding, which is not going to work as expected with this setup. mobdebug.start() should be used instead.
Please see an example of how this debugging can be setup with ZeroBrane Studio here: http://notebook.kulchenko.com/zerobrane/debugging-openresty-nginx-lua-scripts-with-zerobrane-studio. All the details to how paths to mobdebug and required modules are configured should still be applicable to your environment.