clj-fakes is an isolation framework for Clojure/ClojureScript that makes creating test doubles much easier.
- All test doubles are named "fakes" to simplify the terminology.
- Fakes can be created for:
- functions
- instances of protocols and Java interfaces
- "Nice" and "strict" protocol fakes are supported.
- Monkey patching is supported to fake implicit dependencies.
- Several functions are provided for asserting recorded calls.
- Self-testing: automatically checks for unused fakes.
- Informative error messages.
- Test runner agnostic.
- Arrange-Act-Assert style testing.
Requirements: Clojure 1.7.0 and/or ClojureScript 1.7.28 or higher.
Add this to your dependencies:
[clj-fakes "0.5.0"]
Require framework namespace in your unit test source file:
; Clojure
(ns unit.example
(:require
[clj-fakes.core :as f]
; and/or:
[clj-fakes.context :as fc]))
; ClojureScript
(ns unit.example
(:require
[clj-fakes.core :as f :include-macros true]
; and/or:
[clj-fakes.context :as fc :include-macros true]))
Explicit context:
(let [ctx (fc/context)]
; use clj-fakes.context API here
)
Implicit context:
(f/with-fakes
; use clj-fakes.core API here
)
; on exit block will automatically unpatch all patched vars and execute self-tests
All the following examples are assumed to be used inside an implicit context.
(let [foo (f/fake [[1 2] "foo"
[3 4 5] "bar"])]
(foo 1 2) ; => "foo"
(foo 3 4 5) ; => "bar"
(foo 100 200)) ; => raises "Unexpected args are passed into fake: (100 200) ..."
(let [cow (f/reify-fake AnimalProtocol
(sleep :fake [[] "zzz"]))]
(p/sleep cow) ; => "zzz"
(p/speak cow)) ; => undefined method exception
(let [cow (f/reify-nice-fake p/AnimalProtocol)]
(p/sleep cow) ; => FakeReturnValue
(p/speak cow)) ; => FakeReturnValue
(let [foo (f/recorded-fake [[(f/arg integer?) (f/arg integer?)] #(+ %1 %2)])
bar (f/recorded-fake [[(f/arg integer?) (f/arg integer?)] #(* %1 %2)])]
(foo 1 2)
(bar 5 6)
(foo 7 8)
(f/calls foo)
; => [{:args [1 2] :return-value 3}
; {:args [7 8] :return-value 15}]
(f/calls)
; => [[foo {:args [1 2] :return-value 3}]
; [bar {:args [5 6] :return-value 30}]
; [foo {:args [7 8] :return-value 15}]]
)
(let [cow (f/reify-fake p/AnimalProtocol
(speak :recorded-fake [f/any? "moo"]))]
(p/speak cow)
(f/calls (f/method cow p/speak))) ; => [{:args ..., :return-value moo}]
(f/was-called-once foo [1 2])
(f/method-was-called-once p/speak cow ["Bob"])
(f/was-called foo [1 2])
(f/method-was-called p/speak cow ["Bob"])
(f/was-not-called foo)
(f/method-was-not-called p/speak cow)
(f/were-called-in-order
foo [1 2 3]
foo [(f/arg integer?)]
bar [100 200]
baz [300])
(f/methods-were-called-in-order
p/speak cow []
p/sleep cow []
p/eat dog ["dog food" "water"]
p/speak cow ["Bob"])
(f/with-fakes
(f/patch! #'funcs/sum (f/fake [[1 2] "foo"
[3 4] "bar"]))
(funcs/sum 1 2) ; => "foo"
(funcs/sum 3 4)) ; => "bar"
; patching is reverted on exiting with-fakes block
(funcs/sum 1 2) ; => 3
(f/patch! #'funcs/sum (f/recorded-fake [f/any? funcs/sum]))
(funcs/sum 1 2) ; => 3
(f/was-called funcs/sum [1 2]) ; => true
(f/with-fakes
(f/fake [f/any? nil]))
; => raises "Self-test: no call detected for: non-optional fake ..."
(f/with-fakes
(f/recorded-fake))
; => raises "Self-test: no check performed on: recorded fake ..."
More documentation can be found at the project site:
Copyright © 2015 Yuri Govorushchenko.
Released under an MIT license.