What’s the best way to set up a test database for testing an app that uses MongoDB without Ecto?
I’d like the database to be in a clean state between each test.
What’s the best way to set up a test database for testing an app that uses MongoDB without Ecto?
I’d like the database to be in a clean state between each test.
You can drop the db before every test case with:
setup do
Mongo.command(:mongo_name, %{dropDatabase: 1})
end
Sadly this way the db will contain the last test case after all tests have finished, but I couldn’t get it working inside on_exit
edit: I just noticed this question isn’t 2 months, but 3 years and 2 months old. Still, I hope someone will find it useful one day
You can use the mtools to create a MongoDB deployment (Standalone, Replica-Set etc) for the test cases. Then it does not matter, if database of the last test case is not dropped.
If you use this driver you can take a look at the CollectionCase
template:
defmodule CollectionCase do
use ExUnit.CaseTemplate
@seeds ["127.0.0.1:27017", "127.0.0.1:27018", "127.0.0.1:27019"]
setup_all do
assert {:ok, pid} = Mongo.start_link(database: "mongodb_test", seeds: @seeds, show_sensitive_data_on_connection_error: true)
Mongo.admin_command(pid, [configureFailPoint: "failCommand", mode: "off"])
Mongo.drop_database(pid)
{:ok, [pid: pid]}
end
setup do
{:ok, catcher} = EventCatcher.start_link()
on_exit(fn -> EventCatcher.stop(catcher) end)
[catcher: catcher]
end
using do
quote do
import CollectionCase
end
end
defmacro unique_collection do
{function, _arity} = __CALLER__.function
"#{__CALLER__.module}.#{function}"
|> String.replace(" ", "_")
|> String.replace(".", "_")
|> String.replace(":", "_")
|> String.downcase()
end
end
Using the MongoDB 4.4 you can simulate network-errors by using the failCommand
, like this
cmd = [
configureFailPoint: "failCommand",
mode: [times: 1],
data: [errorCode: 6, failCommands: ["count"]]
]
Mongo.admin_command(top, cmd)
{:error, %Error{code: 6, retryable_reads: true}} = Mongo.count(top, coll, %{})
But if you use this, then you need to turn off the async: false
.
The EventCatcher
monitors the commands that sends the driver to MongoDB. You can test whether the program sends the right sequence of commands to the MongoDB.
assert [:count | _] = EventCatcher.retryable_read_events(catcher) |> Enum.map(fn event -> event.command_name end)