It's simple mocking library. You can create a mock function that records all calls and check if it was invoked.
- Mocking return value
- Recording calls
- Checking calls in tests with clojure.test assert expressions
- Instrumenting mocks with malli schema or clojure.spec
You can use git or maven as a dependency source:
{org.clojars.mrroman/memocks {:mvn/version "0.1.2"}}
or
{org.clojars.mrroman/memocks
{:git/url "https://github.com/mrroman/memocks.git" :git/tag "0.1.2" :git/sha "3859de3ea99bd5795cadeba8f4fba3c5252632b2"}}
Import memocks:
(require '[com.siili.memocks :as memocks])Create new mock function:
(def m (memocks/mock))You can call it as any other function and check all recorded calls.
(m :debug "Start process...")
(m :info "Results:")
(m :debug "Stop process...")
(memocks/all-args m)
=> [(:debug "Start process...") (:info "Results:") (:debug "Stop process...")]Checking if the call happened can be cumbersome, so I've implemented a couple of predicates:
(memocks/not-invoked? m)
=> false
(memocks/invoked? m)
=> true
(memocks/invoked? m 3)
=> true
(memocks/invoked? m 2)
=> false
(memocks/invoked-with? m :info "Results:")
=> true
(memocks/invoked-with? m :info "Results:" 3.14159)
=> false
(memocks/invoked-as? (m :info "Results:"))
=> true
(memocks/invoked-as? (m :info "Results:" 3.14159))
=> false
invoked-as?looks a bit likeinvoked-with?but has different semantics. It will be treated as a function invocation to linters so they can check e.g. if function arity is valid.
(memocks/invoked-with?)and(memocks/invoked-as?)use regular=operator to compare arguments.
You can create a mock that returns a value:
(def two (memocks/mock 2))
(two)
=> 2You can also create a mock with a custom function that calculates the result. The function takes as an argument a list with all recorded calls.
(def stub (memocks/mock (fn [calls] (last calls))))
(stub 1)
=> (1)
(stub 2)
=> (2)
(stub 3)
=> (3)In this example, mock will return the last call (a list of arguments).
Memocks provides a convenient macro that allows you to mock functions easily. Let's mock function http/get.
(with-mocks [http/get {:body "OK" :status 200}
http/post {:body "NOK" :status 500}]
(http-get)
(http-post))Memocks uses with-redefs macro provided by Clojure.
Memocks supports Malli function schemas. You can create a mock function instrumented with malli based on schema of a function. E.g.
(require '[malli.core :as m])
(m/=> my-inc [:=> [:cat :int] :int])
(defn my-inc [x]
(inc x))
;; You have to provide a symbol of function
;; or with or without namespace (aliases are supported).
(def my-inc-mock (mock-fn 'my-inc 1))
(my-inc-mock 0)
;=> 1
(my-inc-mock "aa")
;=> An exception ::invalid-input
(def my-inc-mock2 (mock-fn 'my-inc nil))
(my-inc-mock2 1)
;=> An exception ::invalid-outputIf you use with-mocks macro, it will our of the box.
If you use :malli/schema metadata to define schema, you have to use dev/start! to enable mock instrumentation.
Memocks supports clojure.spec function specs. You can create a mock function which will check if arguments and return value conforms with spec. E.g.
(require '[clojure.spec.alpha :as s])
(s/fdef my-inc
:args (s/cat :x int?)
:ret int?)
(defn my-inc [x]
(inc x))
;; You have to provide a symbol of function
;; or with or without namespace (aliases are supported).
(def my-inc-mock (mock-fn 'my-inc 1))
(my-inc-mock 0)
;=> 1
(my-inc-mock "aa")
;=> An exception invalid arguments
(def my-inc-mock2 (mock-fn 'my-inc nil))
(my-inc-mock2 1)
;=> An exception invalid return valueIf you use with-mocks macro, it will our of the box.
Copyright © 2016 Konrad Mrożek
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.