简体   繁体   中英

Midje: having single actual value with multiple arrow functions

Put simply, I would like the code shown below to behave how one could think it should behave, eg defining the left-hand side value (here as a trivial anonymous associative collection) just once and applying multiple different arrow functions (asserions) to it in a clean and idiomatic way:

  (deftest test-test
    (fact "some-fact"
      {:a 1 :b 2}
      =>
          (contains {:a odd?}))
      =not=>
          (contains {:a even?})
    )

This code obviously doesn't work: only => arrow actually asserts and =not=> is irrelevant (eg if we change even? to odd? there the test still passes).

Maybe it's as simple as wrapping in let or using def , but being new to Clojure I would like to know what is the preferred way.

Every checkable must have a left-hand side, an arrow, and a right-hand side, so this code won't work. I also think that Midje is intended as the unit testing library (testing result of one function for different inputs) and you should instead use Spec or Malli for testing data structures.

That said, I think you can achieve that result in several ways:

You can of course repeat your left-hand side value twice:

(fact "some-fact"
      {:a 1 :b 2} => (contains {:a odd?})
      {:a 1 :b 2} =not=> (contains {:a even?}))
=> true

Or insert it into let :

(let [my-map {:a 1 :b 2}]
  (fact "some-fact"
        my-map => (contains {:a odd?})
        my-map =not=> (contains {:a even?})))
=> true

You can use every-checker :

(fact "some-fact"
      {:a 1 :b 2}
      => (every-checker (contains {:a odd? :b even?})
                        #(not (some-> (:a %) even?))))
=> true

You can write some macro, which would transform that code exactly as you wish (if you're really new to Clojure, think twice if you really need to do that):

(defmacro mfact [doc o & args]
  `(fact ~doc
         ~@(mapcat (fn [[x y]] (list o x y))
                   (partition 2 args))))

(mfact "some-fact"
       {:a 1 :b 2}
       =>
       (contains {:a odd?})
       =not=>
       (contains {:a even?}))
=> true

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