This repository has been archived by the owner on Mar 19, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
mock.clj
47 lines (39 loc) · 1.57 KB
/
mock.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
(ns mockfn.mock
(:require [mockfn.matchers :as matchers]))
(defn- matches-arg?
[[expected arg]]
(if (satisfies? matchers/Matcher expected)
(matchers/matches? expected arg)
(= expected arg)))
(defn- matches-args?
[expected args]
(let [arity-matches? (= (count expected) (count args))
each-arg-matches? (every? matches-arg? (map vector expected args))]
(and arity-matches? each-arg-matches? expected)))
(defn- for-args
[m args]
(let [expected (some #(matches-args? % args) (keys m))]
(if expected
(get m expected)
::unexpected-call)))
(defn- unexpected-call [func args]
(format "Unexpected call to %s with args %s." func args))
(defn- return-value-for
[func spec args]
(when (-> spec :return-values (for-args args) #{::unexpected-call})
(throw (ex-info (unexpected-call func args) {})))
(-> spec :times-called (for-args args) (swap! inc))
(-> spec :return-values (for-args args)))
(defn mock [func spec]
(with-meta
(fn [& args] (return-value-for func spec (into [] args)))
spec))
(defn- doesnt-match [function args matcher times-called]
(format "Expected %s with arguments %s %s, received %s."
function args (matchers/description matcher) times-called))
(defn verify [mock]
(doseq [args (-> mock meta :times-expected keys)
matcher (-> mock meta :times-expected (get args))]
(let [times-called (-> mock meta :times-called (get args) deref)]
(when-not (matchers/matches? matcher times-called)
(throw (ex-info (doesnt-match (-> mock meta :function) args matcher times-called) {}))))))