Question

I'm working on a Liberator project in Clojure. I've defined a series of routes which return JSON data computed by logic in some other namespace. I would like to be able to change the namespace that implements the logic programmatically so I can do something like this:

JAVA_OPTS='-DgameLogicNamespace=foo.logic.mock' lein ring server-headless 8080

I am currently doing it like this:

(ns foo.routes
  (:require [compojure.core :refer :all]
            [liberator.core :as lib :refer [defresource request-method-in]]
            [liberator.representation :refer [ring-response]]))

(require
 (vec
  (cons (symbol (System/getProperty "gameLogicNamespace" "foo.logic.real"))
        '[:as logic])))

This works, but feels a bit clunky. Is there an idiomatic way to accomplish what I want?

One of my main motivations is actually for unit testing routes with mock data, so if there's a nice solution for providing the mock logic only in tests (and not as a JVM system property), suggestions are welcome.

Was it helpful?

Solution

One of my main motivations is actually for unit testing routes with mock data, so if there's a nice solution for providing the mock logic only in tests (and not as a JVM system property), suggestions are welcome.

If you haven't already, take a look at ring-mock for some nice utilities to generate mock requests to test your Ring handlers.

If you're interested in providing mock versions of functions that provide the implementation of your application logic during unit tests, consider using with-redefs; it's pretty much custom-made for this purpose.

(ns my-app.handlers-test
  (:require [clojure.test]
            [my-app.handlers :as h]
            [my-app.logic :as l]
            [ring.mock.request :as r]))

(deftest test-simple-handler
  (with-redefs [l/my-complicated-logic #(update-in % [:a] inc)]
    (is (= {:a 2}
           (h/my-handler (r/request :post "/foo" {:a 1}))))))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top