Skip to content

Simple mocking library to use in your Clojure tests.

License

Notifications You must be signed in to change notification settings

mrroman/memocks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

memocks

It's simple mocking library. You can create a mock function that records all calls and check if it was invoked.

Clojars Project

Install

You can use git or maven as a dependency source:

{org.clojars.mrroman/memocks {:mvn/version "0.2.1"}}

or

{org.clojars.mrroman/memocks 
    {:git/url "https://github.com/mrroman/memocks.git" :git/tag "0.2.1" :git/sha "78e4164248e990de2c9ba772e1b1d1feef817752"}}

Usage

Import memocks:

(require '[com.siili.memocks :as memocks])

Simple mock

Create new mock function:

(def m (memocks/mock))

Recorded arguments

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 calls

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 like invoked-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.

Mock returning a value

You can create a mock that returns a value:

(def two (memocks/mock 2))

(two)
=> 2

Mock with a result computing function

You 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).

The result computing function generators

Memocks provides some result providing function generators.

  1. (memocks/return-values val1 ...) generates a function returning values in following calls.
(def m (memocks/mock (memocks/return-values 1 2 3)))

(m)
=> 1

(m)
=> 2

(m)
=> 3

If there are no more values it throws an exception.

  1. (memocks/return-matching call1 val1 call2 val2 ...) generator a function returning values for matching calls. You can provide a default value for non-matching call with :com.silli.memocks/default.
(def m (memocks/mock (memocks/return-matching [:a :b] 1 [:c] 2 ::memocks/default 3)))

(m :a :b)
=> 1

(m :c)
=> 2

(m :d)
=> 3

If there's no matching call, it throws an exception.

Mocking symbols

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.

Malli support

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-output

If 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.

clojure.spec support

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 value

If you use with-mocks macro, it will our of the box.

License

Copyright © 2016 Konrad Mrożek

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

About

Simple mocking library to use in your Clojure tests.

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •