Common Lisp有一个模拟/存根框架吗?

Eri*_*ebo 11 lisp tdd unit-testing mocking common-lisp

Common Lisp有一个模拟/存根框架吗?

EmacsLispMock看起来很棒,但它是一个Emacs lisp框架,我正在寻找可以从Common Lisp中使用的东西.

有什么建议?

650*_*502 5

以下应该做您想要的

(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))
Run Code Online (Sandbox Code Playgroud)

宏仅保存符号当前指向的函数,并用提供的存根实现替换它。在该块的末尾,该功能将恢复为原始值。

添加保护措施以防止身体非本地退出可能是有意义的。

还要注意,如果编译器内联了函数调用,显然更改函数定义是行不通的。CL有一个特殊的NOTINLINE声明,可用于防止此问题。

  • 应当指出,这可能不一定在编译代码中起作用,因为文件编译器可以内联函数(例如,编译器可以假设同一文件中的函数保持不变)。因此,可能有必要声明这些函数不内联。 (6认同)