Skip to content

Instantly share code, notes, and snippets.

@hospadar
Last active November 21, 2016 17:44
Show Gist options
  • Save hospadar/1f20f091b9427c17c22b7b3f00d339b0 to your computer and use it in GitHub Desktop.
Save hospadar/1f20f091b9427c17c22b7b3f00d339b0 to your computer and use it in GitHub Desktop.
Clojure macro to create fake java objects
;Useful macro for creating objects that can be called like java objects.
;Handy for testing clojure functions that use java objects directly.
;Allows you easily create mock objects that can be passed into clojure functions
;EX: you have a clojure function that takes a curator LeaderLatch - the only functions you actually call are start(), hasLeadership(), and close()
;It would be a major hassle to implement a leader-latch subclass just to test that the function doesn't do any work unless it hasLeadership.
;You could implement a quick fake leader latch like:
;(fake-object
; (close [this] (comment "no-op"))
; (start [this] (comment "no-op"))
; (hasLeadership [this] true))
;
; Then you can call dot-functions on your object
;(def mock
; (fake-object
; (close [this] (comment "no-op"))
; (start [this] (comment "no-op"))
; (hasLeadership [this] true))
;
; (.start mock)
; (.hasLeadership mock) ;=> returns true
(defmacro fake-object
[& funcs]
(let [iface (gensym "fake-object")
func-sigs (->> funcs
(map #(take 2 (update-in
(vec %)
[1]
(fn [a] (vec (rest a)))))))]
(eval `(definterface ~iface ~@func-sigs))
`(reify ~iface
~@funcs)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment