Using jetty for testing clojure web apps

I’m a big fan of functional tests that work at the level of a user of an application. While working on web applications in clojure, I’ve even written kerodon, a library to keep cookies around between ring requests to make writing them easier. However, there are times when a running a server is useful.

Thanks to jetty, it is easy to setup a test fixture to start a server.

(declare test-port)

(defn with-server
  [f]
  (let [server (jetty/run-jetty #'app {:port 0 :join? false})
        port (-> server .getConnectors first .getLocalPort)]
    (with-redefs [test-port port]
      (try
        (f)
        (finally
          (.stop server))))))
          
(use-fixtures :once with-server)

(def url [relative]
 (str "http://localhost:" test-port relative))

Then the url function can be used to make a url pointing to the running server. There are a few cases where this is useful:

  1. In clojars we have some tests that start a server, use pomegranate to perform actions, and check the repo and local maven cache state. This is the highest level test possible, using the actual library lein uses to gather dependencies, and checking it against a live server.
  2. In com.cemerick/friend the functional tests use clj-http to query against a live server.
  3. If a javascript environment is needed, a server can be started and a library like clj-webdriver can run a browser or PhantomJS against it.