Skip to content

Metaconstants as partial packets of values

marick edited this page Aug 6, 2011 · 1 revision

This feature is experimental, starting in 1.3-alpha1.

You can instruct Midje to treat metaconstants like maps or records.

##Short version

Metaconstants can be made to include key/value pairs:

(fact
  (fullname ...person...) => "Brian Marick"
  (provided
    ...person... =contains=> {:given "Brian", :family "Marick"}))

Metaconstants can be used as background prerequisites:

(fact "`keys`, `values`, and `contains` work on metaconstants"
  (against-background ..m.. =contains=> {:a 3, :b 4})
  (keys ..m..) => [:a :b]
  (vals ..m..) => [3 4]
  (contains? ..m.. :a) => truthy
  (contains? ..m.. :c) => falsey)

##The longer version

Metaconstants are tokens that let you describe only what's important to make a particular fact true. Most often they're used with function prerequisites:

(fact (this 1) => 2
  (provided (that 1) => 3)

Languages like Ruby and Smalltalk prevent you from direct access to values in an object. Clojure allows it; indeed, it's idiomatic to use keyword access with maps and records:

user> (def mymap {:a 1})
#'user/mymap
user> (:a mymap)
1

You could declare an accessor function:

user> (def get-a :a)
#'user/get-a
user> (get-a mymap)
1

In practice, people don't. In Clojure it's idiomatic to use keyword accessors to inform humans reading the code that it's talking about simple data: no lazy getters that reach over the network or into a database to fetch or calculate a simple value. I myself lean toward the Ruby style, but Midje should support idiomatic Clojure. Therefore, you can treat a metaconstant as a collection of key/value pairs, deferring until later whether it should be a map, a defrecord, a deftype, etc.

Setting a metaconstants values is done in the provided clause:

(fact
  (:a ..mc..) => 5
  (provided ..mc.. =contains=> {:a 5}))

It's also convenient to use an against-background clause to set up a metaconstant for an entire fact:

(fact "keys, values, and contains work on metaconstants"
  (against-background ..m.. =contains=> {:a 3, :b 4})
  (keys ..m..) => [:a :b]
  (vals ..m..) => [3 4]
  (contains? ..m.. :a) => truthy
  (contains? ..m.. :c) => falsey)
Clone this wiki locally