summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
authorMichal Nazarewicz <mina86@mina86.com>2016-02-23 14:44:56 +1100
committerLars Ingebrigtsen <larsi@gnus.org>2016-02-23 14:44:56 +1100
commit6f0498bf290cbe066036f8bfe0d09ad99ddaab03 (patch)
tree391e4f25adbbe7d88e1f968bbef54ddeb1dcda84 /lisp/emacs-lisp
parent96e32bbb736ec6e0a7278ae864098c7c812b05a4 (diff)
downloademacs-6f0498bf290cbe066036f8bfe0d09ad99ddaab03.tar.gz
emacs-6f0498bf290cbe066036f8bfe0d09ad99ddaab03.tar.bz2
emacs-6f0498bf290cbe066036f8bfe0d09ad99ddaab03.zip
ert-with-function-mocked: New macro
* lisp/emacs-lisp/ert-x.el (ert-with-function-mocked): New macro which allows evaluating code while particular function is replaced with a mock. The original definition of said function is restored once the macro finishes.
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/ert-x.el40
1 files changed, 40 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el
index 2a2418fa7d2..eb10c845d3f 100644
--- a/lisp/emacs-lisp/ert-x.el
+++ b/lisp/emacs-lisp/ert-x.el
@@ -285,6 +285,46 @@ BUFFER defaults to current buffer. Does not modify BUFFER."
(kill-buffer clone)))))))
+(defmacro ert-with-function-mocked (name mock &rest body)
+ "Mocks function NAME with MOCK and run BODY.
+
+Once BODY finishes (be it normally by returning a value or
+abnormally by throwing or signalling), the old definition of
+function NAME is restored.
+
+BODY may further change the mock with `fset'.
+
+If MOCK is nil, the function NAME is mocked with a function
+`ert-fail'ing when called.
+
+For example:
+
+ ;; Regular use, function is mocked inside the BODY:
+ (should (eq 2 (+ 1 1)))
+ (ert-with-function-mocked ((+ (lambda (a b) (- a b))))
+ (should (eq 0 (+ 1 1))))
+ (should (eq 2 (+ 1 1)))
+
+ ;; Macro correctly recovers from a throw or signal:
+ (should
+ (catch 'done
+ (ert-with-function-mocked ((+ (lambda (a b) (- a b))))
+ (should (eq 0 (+ 1 1))))
+ (throw 'done t)))
+ (should (eq 2 (+ 1 1)))
+"
+ (declare (indent 2))
+ (let ((old-var (make-symbol "old-var"))
+ (mock-var (make-symbol "mock-var")))
+ `(let ((,old-var (symbol-function (quote ,name))) (,mock-var ,mock))
+ (fset (quote ,name)
+ (or ,mock-var (lambda (&rest _)
+ (ert-fail (concat "`" ,(symbol-name name)
+ "' unexpectedly called.")))))
+ (unwind-protect
+ (progn ,@body)
+ (fset (quote ,name) ,old-var)))))
+
(provide 'ert-x)
;;; ert-x.el ends here