Fix tests for new return values.
[cl-mock.git] / README.md
1 -*- mode: markdown; coding: utf-8-unix; -*-
2
3 CL-MOCK - Mocking (generic) functions.
4
5 Copyright (C) 2013-14 Olof-Joachim Frahm
6
7 Release under a Simplified BSD license.
8
9 Working, but unfinished.
10
11 Should be portable thanks to [`CLOSER-MOP`][1].
12
13
14 # INTRODUCTION
15
16 This small library provides a way to replace the actual implementation
17 of either regular or generic functions with mocks.  How to integrate
18 this facility with a testing library is up to the user; the tests for
19 the library are written in [`FIVEAM`][2] though, so most examples will
20 take that into account.
21
22 Since it is pretty easy to just roll something like this on your own,
23 the main purpose is to develop a nice (lispy, declarative) syntax to
24 keep your tests readable and maintainable.
25
26 Some parts may be used independently of the testing facilities,
27 e.g. dynamic `FLET` and method bindings with `PROGM` may be of general
28 interest.
29
30
31 # MOCKING CONTEXT
32
33 In addition to having macros and functions to install bindings into the
34 mocking context, the actual context object may be retrieved and passed
35 around as well.  This might be useful for further analysis or other
36 helpers.
37
38
39 # GENERIC FUNCTIONS
40
41 Since behaviour isn't bound to classes, but to generic functions,
42 creating new classes on the fly isn't particularly interesting.  If
43 necessary, additional shortcuts will be added, but until then I don't
44 see the need for this.  On the contrary, providing a way to temporarily
45 supersede generic function bindings sounds like a more viable approach,
46 especially with regards to (custom) method combinations.
47
48 Thus, the form `PROGM` is provided to bind a number of methods during
49 the execution of its body:
50
51     > (progm
52     >     '((baz NIL (list)))
53     >     '((lambda (list) list))
54     >   ...)
55
56 For example:
57
58     > (defclass foo () ())
59     > (defgeneric baz (foo)
60         (:method ((foo foo))
61           42))
62     > (progm '((baz NIL (list)))
63              '((lambda (list) list))
64         (values (baz (make-instance 'foo)) (baz '(1 2 3))))
65     > => 42
66     > => (1 2 3)
67
68 This is implemented via [`CLOSER-MOP`][1], so compatiblity with that
69 library is required.
70
71
72 # UTILITIES
73
74 `DFLET` dynamically rebinds functions similar to `FLET`:
75
76     > (defun foo () 42)
77     > (defun bar () (foo))
78     > (bar)
79     > => 42
80     > (dflet ((foo () 23))
81     >   (bar))
82     > => 23
83     > (OR) => 42, if FOO was inlined
84
85 The caveat is that this might not work on certain optimisation settings,
86 including inlining.  That trade-off seems acceptable; it would be nice
87 if a warning could be issued depending on the current optimisation
88 settings, however that is particularly implementation dependent, so lack
89 of a warning won't indicate a working environment.
90
91 The underlying function `PROGF` may be used as well similarly to the
92 standard `PROG`:
93
94     > (progf '(foo) (list (lambda () 23))
95     >   (bar))
96     > => 23
97     > (OR) => 42, if FOO was inlined
98
99 [1]: http://common-lisp.net/project/closer/closer-mop.html