有没有办法在 clojure 中测试 System/exit?

Is there a way to test System/exit in clojure?

我有运行 (System/exit 0) 的代码,我想测试那部分代码。我尝试使用 with-redefs 对其进行测试,但我发现我不允许对 Java 方法执行此操作。我该如何进行测试?

抱歉,您不能直接模拟该函数,尽管像所有好的 CS 问题一样*您可以通过添加一个额外的间接级别来解决它:

(defn exit-now! [] 
   (System/exit 0))

然后在您的测试中,您可以使用 -redef 退出对 clojure 函数 exit-now 的调用。

(with-redefs [exit-now! (constantly "we exit here")]
    (is (= "we exit here" (code that calls exit))))

也许您可以促使该功能的开发人员放弃从项目深处调用 System/exit 的做法。

*当然性能问题除外。

如果您确实需要测试对 System/exit 的调用,您可以使用 SecurityManager 来禁止它们,然后捕获结果 SecurityExceptions:

(System/setSecurityManager
  (proxy [SecurityManager] []
    (checkExit [status]
      (throw (SecurityException.
               (str "attempted to exit with status " status))))
    (checkCreateClassLoader []
      true)
    (checkPermission [_]
      true)))

(System/exit 5)
;> SecurityException attempted to exit with status 5  user/eval6/fn--11 (NO_SOURCE_FILE:2)

(try (System/exit 5) (catch SecurityException e :foo))
;= :foo

不过,一般来说,像 Arthur 建议的那样将方法调用包装在一个函数中往往是更明智的方法。