Testing static routes in compojure

1.2k views Asked by At

I am trying to write a test for the compojure static content route. I am testing the routes by examining the ring response directly.

A minimal working example is as follows:

;; src/testing-webapps.core.clj
(ns testing-webapps.core
  (:use [compojure.core]
        [compojure.route   :as route]))

(defroutes web-app
   (route/resources "/")
   (route/not-found "404"))


;; test/testing-webapps.core_test.clj
(ns testing-webapps.core-test
  (:require [clojure.test :refer :all]
            [testing-webapps.core :refer :all]))

(defn request [resource web-app & params]
  (web-app {:request-method :get :uri resource :params (first params)}))

(deftest test-routes
  (is (= 404 (:status (request "/flubber" web-app))))
  (is (= "404" (:body (request "/flubber" web-app))))
  (is (= 200 (:status (request "/test.txt" web-app)))))

Testing the 404 route works fine but calling (request "/test.txt" web-app) leads to an unexpected NullPointerException in ring.middleware.file-info/not-modified-since?.

Here is the top part of the stacktrace:

ERROR in (test-routes) (file_info.clj:27)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.NullPointerException: null
 at ring.middleware.file_info$not_modified_since_QMARK_.invoke (file_info.clj:27)
    ring.middleware.file_info$file_info_response.doInvoke (file_info.clj:44)
    clojure.lang.RestFn.invoke (RestFn.java:442)
    ring.middleware.file_info$wrap_file_info$fn__917.invoke (file_info.clj:64)
    [...]

The static route works fine in the browser but not when called through my request function.

Is there an easier way to test a static route in compojure and why do I get a NullPointerException when calling the static route with my own request map?

1

There are 1 answers

1
overthink On BEST ANSWER

Looking at the source for not-modified-since?, I think the issue is you have no headers in your request map, so it throws a NPE on this expr: (headers "if-modified-since"). Try changing your request method like so:

(defn request [resource web-app & params]
  (web-app {:request-method :get 
            :headers {"content-type" "text/plain"} ; added a header
            :uri resource 
            :params (first params)}))

You might also consider using ring-mock to create requests for testing. It insulates you a little bit from stuff like this.