Search code examples
clojurebddspeclj

Reusing a stub/redef across a speclj context


I'm writing tests for a Clojure app using Speclj. I'm accustomed in BDD to do things like this:

context "some context"
  stub my-function :return true
  it "has behavior one"
    should true my-function
  it "has behavior two"
    should_not false my-function

But in Speclj I can't seem to find an example of how to share the stub across the characteristics, so I'm currently stuck writing code like this:

(describe "this"
  (context "that"
    (it "accepts nil"
      (with-redefs [called-fn (constantly nil)]
          (should= nil (my-fn nil)))))
    (it "accepts 1"
      (with-redefs [called-fn (constantly nil)]
          (should= 100 (my-fn 1))))))

(I realize this is a somewhat contrived example and arguably those assertions could all go under one characteristic, but let's suppose for now that I have good reason to write the code like this.)

I want, however, to just have to stub called-fn once, but moving this up out of the its raises errors because the real called-fn gets called instead of my redef.

Is there a way to reuse redefs (or use Speclj stubs) in Speclj so I'm not stuck pushing them all down inside the characteristics?


Solution

  • You can use the around macro to accomplish this.

    Here's an example spec:

    (ns sample.core-spec
      (:require [speclj.core :refer :all]
                [sample.core :refer :all]))
    
    (describe "a test"
      (it "returns output from fn-a"
        (should= 1 (fn-b)))
    
      (describe "using with-redef"
        (around [it] (with-redefs [fn-a (fn [] 2)] (it)))
    
        (it "returns the output from redefined function"
          (should= 2 (fn-b)))))
    

    Source:

    (ns sample.core)
    
    (defn fn-a []
      1)
    
    (defn fn-b []
      (fn-a))