I have code that runs (System/exit 0) and I want to test that portion of the code. I tried testing it with with-redefs but I found out I'm not allowed to do that for Java methods. How can I go about testing this?
-
1I would argue that you should rather try to avoid calling System/exit outside of your main function (assuming that this is code that you can actually change) - for individual components of your program to exit the program itself is a violation of the separation of concerns, which is also why it's hard to test.bsvingen– bsvingen2015-03-26 21:41:47 +00:00Commented Mar 26, 2015 at 21:41
2 Answers
Sorry, you cannot directly mock that function, though like all good CS problems* you can solve it by adding one extra level of indirection:
(defn exit-now! []
(System/exit 0))
then in your tests you can with-redef out the call to the clojure function exit-now.
(with-redefs [exit-now! (constantly "we exit here")]
(is (= "we exit here" (code that calls exit))))
and perhaps you could nudge the developers of that function away from the practice of calling System/exit from deep within a project.
*except performance problems of course.
Comments
If you really need to test calls to System/exit, you can use a SecurityManager to disallow them and then catch the resulting 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
In general, though, wrapping the method call in a function like Arthur suggested tends to be the saner approach.