Is there a mocking/stubbing framework for Common Lisp?
EmacsLispMock looks great, but it is an Emacs lisp framework, and I'm looking for something to use from Common Lisp.
Any suggestions?
A few years later, there is. We have cl-mock and mockingbird both in Quicklisp.
(ql:quickload :mockingbird)
This one also allows to check if a function was called, if so how many times and with which arguments and it's possible to stub individual methods.
The following should do what you're looking for
(defmacro with-replaced-function (fdef &rest body)
(let ((oldf (gensym))
(result (gensym))
(name (car fdef))
(args (cadr fdef))
(rbody (cddr fdef)))
`(let ((,oldf (symbol-function ',name)))
(setf (symbol-function ',name) (lambda ,args ,@rbody))
(let ((,result (progn ,@body)))
(setf (symbol-function ',name) ,oldf)
,result))))
(defmacro show (x)
`(format t "~a --> ~a~%"
',x ,x))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun foo (x y) (+ x y))
(defun bar (x) (foo x (* x 2)))
(show (bar 42))
(show (with-replaced-function (foo (x y) (* x y))
(bar 42)))
(show (bar 42))
The macro simply saves the function being currently pointed by the symbol and replaces it with the provided stub implementation. At the end of the block the function is restored to the original value.
It would probably make sense to add a protection against non-local exits from the body.
Note also that obviously changing a function definition is not going to work if function calls have been inlined by a compiler. CL has a special NOTINLINE declaration that can be used to prevent this problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With