简体   繁体   中英

In Clojure and Midje, how can I write prerequisites for an indirect call?

In the following code, I'd like to test the foo function before implementing the bar function.

(unfinished bar)

(def tbl {:ev1 bar})
(defn foo [ev] ((tbl ev)))

(fact "about an indirect call"
  (foo :ev1) => nil
  (provided
    (bar) => nil))

But Midje says:

FAIL at (core_test.clj:86)
These calls were not made the right number of times:
    (bar) [expected at least once, actually never called]

FAIL "about an indirect call" at (core_test.clj:84)
    Expected: nil
      Actual: java.lang.Error: #'bar has no implementation,
      but it was called like this:
(bar )

I thought that 'provided' couldn't hook the bar function because the foo didn't directly call the bar. But I also found if I changed the second line like this:

(def tbl {:ev1 #(bar)})

then the test succeeded.

Is there any way to succeed for the first version?

Thanks.

PS: I'm using Clojure 1.5.1 and Midje 1.5.1.

provided uses a flavour of with-redefs to alter the root of a var . When defining tbl you already dereference the var #'bar , prompting tbl to contain the unbound value instead of a reference to the logic to be executed. You cannot provide replacements for already evaluated values is what I'm trying to say.

Similarly:

(defn x [] 0)
(def tbl {:x x})
(defn x [] 1)
((:x tbl)) ;; => 0

What you want is to store the var itself in tbl :

(defn x [] 0)
(def tbl {:x #'x})
(defn x [] 1)
((:x tbl)) ;; => 1

Same for your tests. Once you use (def tbl {:ev1 #'bar}) , they pass.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM