Fork me on GitHub
#testing
<
2017-08-04
>
albaker02:08:27

is there a best practice for database testing, e.g mocks for clojure.java.jdbc?

roberto14:08:01

when I want to mock something in clojure that has side effects, like database access or network io, I normally create a protocol for that, and then have a test and production implementation. Not sure if this is the best way to do it.

seancorfield15:08:45

That's a reasonable way to do it, unless the surface area of the API you're using is big enough that becomes a pain.

seancorfield15:08:47

An alternative is isolating your DB-accessing code from you business logic and testing the business logic separately -- more pure FP. Can be hard if you have a lot of DB access.

seancorfield15:08:33

Or just use a test DB connection and setup/teardown test data around your tests. That's what we do for a lot of our data-intensive functions/tests.

mattly17:08:26

I do the protocol thing as well, using a sort-of repository pattern defining specific queries and mutations against the database as well (or a part thereof).

mattly17:08:42

for tests of the surrounding business logic, I can then mock the db with an in-memory store, and then the actual implementation that talks to the database has its own focused tests.

seancorfield17:08:55

One important issue to bear in mind is that if you're trying to test actual SQL queries, you need to test it against a real database and it needs to be the one (you're planning to use) in production -- since the lightweight / in-memory / local file databases don't support the same SQL operations as the Big Ones do.

seancorfield17:08:11

@albaker So it really depends on exactly what you're trying to test.

albaker18:08:15

I was thinking more like a lein profile w/ a testdb that gets spun up each time, or something along those lines

roberto18:08:32

if you use protocols, you can have a testdb settings in your test that uses the testdb

roberto18:08:03

the db name, host ,etc could be changed when that Database is initialized. I normally use a component for that

roberto18:08:22

then all my queries in test use that component

roberto18:08:35

in dev they use a different one, and in prod the production-ready one

roberto18:08:00

you can externalize those settings too

seancorfield18:08:41

Yeah, we have a Database Component (Stuart Sierra) and initialize it differently in dev/qa/prod (from external config files), then we have a dev-only script that tears down and builds a test DB (with a bunch of essentially random-but-conforming data). We use Boot so it's easy to write new build tasks (as Clojure functions) -- we have a lot of machinery in our build.boot file, including DB migrations (schema changes), data migrations (data changes), etc.

michaelblume21:08:52

I find tests run quite fast against a db if I run them in a transaction and roll the transaction back — you can run your migration once at the start of the test suite and then run everything else on top of that