Search code examples
unit-testingclojuremockingmidje

Mocking protocol implementations in Midje


Is there any way to mock (not stub) a protocol function with Midje (clojure) using something like the "provided" syntax?

This is simial to the question in: Mocking Clojure protocols, but with mocking.

In more detail: I have a protocol and a function that returns something that implements it. I would like to stub the function to return a mock of the protocol and I would like to register an expectation on one of the functions of the mocked protocol "implementation".

edit - here is an example:

There is a protocol and it's implementation:

(defprotocol Thiny (go-bump [_ _]))
(deftype TheThing []
  Thiny
  (go-bump [_ _] 23))

There is a function that returns an implementation of a protocol:

(defn gimme [] (TheThing.))

TheThing might be a DB or network connection or some other nasty thing you want to get rid of in the test.

Then, there is the function I want to test:

(defn test-me [n]
  (let [t (gimme)]
    (-> t (go-bump n))))

I want to make sure it calls go-bump with n.

This is my first attempt to create a test. But it is only halfway done, I would like to setup expectations on the Thiny returned by gimme:

(fact
  (test-me 42) => 42
  (provided (gimme) => (reify Thiny (go-bump [_ n] n))))

Solution

  • For posterity. Here is a working test:

    (fact
      (test-me 42) => 42
      (provided (gimme) => :the-thingy)
      (provided (go-bump :the-thingy 42) => 42))
    

    The trick was to use multiple provided statements that tie into each other.

    Wierd observation. The same way of testing doesn't work for a function that uses the other syntax for calling functions on the protocol. No idea why.

    (defn test-me2 [n]
      (let [t (gimme)]
         (.go-bump t n)))