Database Tests with Rollbacks in Clojure Tweet Vote on HN

Image by vassl

I recently purchased a beta version of Eric Normand’s Intro to clojure.test screencast. In it, he demonstrates how to use the use-fixtures function to set up and tear down state for tests. The function can be used for :each test run, or :once . For example:

( ns myapp.db-test ( :require [ clojure.test :refer :all ] [ myapp.db :as db ] [ myapp.migrations :as migrate )) ( def database-url "jdbc:postgresql://localhost/myapp_test" ) ( use-fixtures :once ( fn [ f ] ( migrate/-main database-url ) ( f )))

The above code sets up a fixture that will be run once for the namespace. In this case, it will run our database migrations.

While working on a Clojure side project recently, I needed a way to reset a database to a known state after each test was run. Since I was using Clojure’s JDBC library, I knew that I could use transactions, and have each test roll back their changes. This is where use-fixtures and its :each option comes in handy.

( ns myapp.db-test ( :require [ clojure.test :refer :all ] [ clojure.java.jdbc :as jdbc ] [ myapp.db :as db ] [ myapp.migrations :as migrate )) ( declare ^ :dynamic *txn* ) ( def database-url "jdbc:postgresql://localhost/myapp_test" ) ( use-fixtures :once ;; same as above) ( use-fixtures :each ( fn [ f ] ( jdbc/with-db-transaction [ transaction database-url ] ( jdbc/db-set-rollback-only! transaction ) ( binding [ *txn* transaction ] ( f )))))