Library agnostic way to stub HTTP endpoints in Clojure
Clojure Shell
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
doc
src/stub_http
test/stub_http
.gitignore
.travis.yml
LICENSE
README.md
logo.png
project.clj
release.sh

README.md

Logo Build Status MIT License

A Clojure library designed to stub HTTP responses regardless of which client library that is used to make the actual HTTP requests.

There are several client specific "http mocking/stubbing/faking" libraries out there such as clj-http-fake and ring-mock but they work on the level of the library and not the HTTP level. I couldn't find a client agnostic library for stubbing HTTP endpoints so I sat out to write one myself based on nanohttpd. This is useful if you want to test your app against a real HTTP server with actual HTTP requests. And even if you don't want to this it may be your only option if you're (for example) using a Java library that makes HTTP requests and you want to stub/fake its responses.

Latest version

The latest release version of stub-http is hosted on Clojars:

Current Version

Usage

(ns x.y
  (:require [stub-http.core :refer :all]))

(with-routes! 
	{"/something" {:status 200 :content-type "application/json" :body (json/generate-string {:hello "world"}) :delay 1000 :counter (atom 0)}
	 {:path "/y" :query-params {:q "something"}} {:status 200 :content-type "application/json" :body  (json/generate-string {:hello "brave new world"})}}
	 ; Do actual HTTP request
	 )

Documentation

  1. See wiki.
  2. An introduction can also be found in this blog post.

Full Examples

Example 1 - Simple Macro

Example demonstrating integration with clojure test and clj-http-lite. This example matches path "/something" and returns the json document

{ "hello" : "world" }

as response:

(ns stub-http.example1
  (:require [clojure.test :refer :all]
            [stub-http.core :refer :all]
            [cheshire.core :as json]
            [clj-http.lite.client :as client]))

(deftest Example1  
    (with-routes!
      {"/something" {:status 200 :content-type "application/json"
                     :body   (json/generate-string {:hello "world"})}}
      (let [response (client/get (str uri "/something"))
            json-response (json/parse-string (:body response) true)]
        (is (= "world" (:hello json-response))))))

Example 2 - Explicit Start and Stop

This example matches only a GET request with a query param "name" equal "value" using the start! function:

(ns stub-http.example2
  (:require [clojure.test :refer :all]
            [stub-http.core :refer :all]
            [cheshire.core :as json]
            [clj-http.lite.client :as client]))

(declare ^:dynamic *stub-server*)

(defn start-and-stop-stub-server [f]
  (binding [*stub-server* (start! {{:method :get :path "/something" :query-params {:name "value"}}
                                   {:status 200 :content-type "application/json" :body (json/generate-string {:hello "world"})}})]
    (try
      (f)
      (finally
        (.close *stub-server*)))))

(use-fixtures :each start-and-stop-stub-server)

(deftest Example2
    (let [response (client/get (str (:uri *stub-server*) "/something"))
          json-response (json/parse-string (:body response) true)]
      (is (= "world" (:hello json-response)))))

Example 3 - Using start! and with-open

The start! function return a Clojure record that implements Closeable. This means that you can use it with the with-open macro:

(ns stub-http.example3
  (:require [clojure.test :refer :all]
            [stub-http.core :refer :all]
            [cheshire.core :as json]
            [clj-http.lite.client :as client]))

(deftest Example3
  (with-open [server (start! {"/something" {:status 200 :content-type "application/json"
                                            :body   (json/generate-string {:hello "world"})}})]
      (let [response (client/get (str (:uri server) "/something"))
            json-response (json/parse-string (:body response) true)]
        (is (= "world" (:hello json-response)))))

Project Status

The project is in an early phase and some changes are to be expected.

Project Stats

License

Copyright (c) 2017 Johan Haleby

Released under the MIT License.

Contributors