gfredericks / vcr-clj

Generic IO playback for clojure
117 stars 20 forks source link

vcr-clj

Circle CI

vcr-clj is a general function recording/playback library for Clojure. It is intended to be used when testing code that does I/O, to achieve several goals:

Any clojure function (er, var) can be recorded and played back.

Requirements

vcr-clj requires Clojure 1.4 or later.

Obtention

[com.gfredericks/vcr-clj "0.4.22"]

Usage

An example with clojure.test:

(ns my.project-test
  (:require [clojure.test :refer :all]
            [vcr-clj.core :refer [with-cassette]]))

(deftest here-is-my-test
  (with-cassette :foo [{:var #'my.io.ns/get-data, ...extra options...}]
    ... do some testy things ...
    ... that call my.io.ns/get-data ...))

There is also currently a separate namespace for recording clj-http requests in particular:

(ns my.project-test
  (:require [clojure.test :refer :all]
            [vcr-clj.clj-http :refer [with-cassette]]))

(deftest here-is-my-webby-test
  (with-cassette :foo
    ... do some testy things ...
    ... that call clj-http functions ...))

(deftest this-test-only-records-some-calls
  (with-cassette {:name :foo-2
                  :recordable? (fn [req] (worth-recording? req))}
    ... do some testy things ...
    ... that call clj-http functions ...))

The first time you run a with-cassette block, a cassette file is created in the /cassettes directory. Each subsequent time, playback is performed using the cassette in the directory. You can delete it to force a re-record.

Namespaced keywords can be used to group cassettes in the filesystem.

Customizing

Each var that is recorded can be customized with options:

Cassette Customization

Instead of invoking with-cassette with a name, you may invoke it with a map defining additional cassette data:

De/serialization

vcr-clj uses Puget for storing cassettes on disk. The :serialization cassette key allows clients to customize the default configuration. The options available are:

The following example prints the raw bytes from a byte array instead of using the default base64 encoding.

(ns my.project-test
  (:require [clojure.test :refer :all]
            [puget.printer :as printer]
            [vcr-clj.cassettes.serialization :as vcr-ser]
            [vcr-clj.core :as vcr]))

(def byte-array-class
  "Standard Java class for byte arrays"
  (class (byte-array 0)))

(defn extended-print-handlers
  "Print handler for vcr-clj library. Enables support of additional object
  instances alongside vcr-clj defaults."
  [cls]
  (when (isa? cls byte-array-class)
    (printer/tagged-handler
      'my.project/printable-bytes
      (fn [data]
        (vcr-ser/split-bytes data 75)))))

(deftest here-is-my-bytes-test
  (with-cassette {:name :testaroo
                  :serialization {:print-handlers extended-print-handlers
                                  :data-readers {'my.project/printable-bytes (comp (fn [string] (.getBytes string))
                                                                                   vcr-ser/maybe-join)}}}
    ... do some testy things ...
    ... that will return byte arrays ...))

TODO

License

Copyright (C) 2012 Gary Fredericks

Distributed under the Eclipse Public License, the same as Clojure.