EzDev.org

Midje

Midje provides a migration path from clojure.test to a more flexible, readable, abstract, and gracious style of testing


How is 'provided' implemented in a fact in Midje?

I was reading Clojure in Action chapter 8 about TDD and experimented with the stubbing macro. It uses the dynamic binding mechanism to stub functions. Alas, in Clojure 1.3 it is not possible to use the binding mechanism for non-dynamic vars, so the stubbing macro doesn't work in most cases, unless you explicitly declare the var which points to a function dynamic. Then I wondered how stubbing is done in Midje and tried to find the source for 'provided', but I couldn't find it. So here it goes:

How is 'provided' implemented in a fact in Midje? Can someone explain this in detail?


Source: (StackOverflow)

Clojure Unit testing : Check if a function was called

I'm trying to write some unit tests for my clojure function (I'm using clojure.test, but I can switch to midje if necessary).

I have a function that reads like :

(defn GenerateNodes
   [is-sky-blue? hot-outside? name]
   (cond
     (is-sky-blue? name) (generate-sky-nodes)
     (hot-outside?) (generate-hot-nodes)))

when unit testing this function, I want to write the following test case :

(deftest when-sky-blue-then-generate-sky-nodes
   (let [is-sky-blue true]
       (GenerateNodes (fn[x] println "sky nodes generated."))
          (is (= true Was-generate-hot-nodes-called?))

How can I assert that the function generate-sky-nodes was called ? or not ? I would use a mocking framework in C# or java, but I don't know about clojure.


Source: (StackOverflow)

reusing setup and teardown with against-background in midje

I have a number of midje facts that have setup/teardowns that are almost, but not quite, entirely the same.

(against-background [(before :contents (setup!)) (before :contents (data)) (before :facts (set-access)) (after :contents (teardown!)]
  (facts "about this thing i am testing "
    ; ...
  ))

(against-background [(before :contents (setup!)) (before :contents (data)) (before :facts (set-other-access)) (after :contents (teardown!)]
  (facts "about this other thing i am testing "
    ; ...
  ))

I would like to wrap the backgrounds into something reusable and preferably paramterizable so I can reuse them, but having trouble doing so. Midje tells me anything other than the above is not the expected background form.


Source: (StackOverflow)

Using midje provided in a let clause doesn't stub methods

When I make a test using an outer let clause to structure some definitions and calls, the stubs don't work the way I'd expect. For example:

This test fails

(fact "blah"
  (let [x (meth1 123)]
    x => 246
    (provided
      (meth2 123) => 246)))

With this code

(defn meth2 [x]
  (prn "meth2" x)
  (* 3 x))

(defn meth1 [x]
  (let [y (meth2 x)]
    y))

Am I not supposed to use let statements with midje? I can't understand how to get these to pass without removing the let.


Source: (StackOverflow)

Clojure/Midje using AOT compilation with tests inside source fails to run

I'm trying to include midje "facts" alongside my source code in a project which uses aot. Trying to access the repl or run the project results in the following error, I've included a minimal sample project which reproduces the issue. Thanks for any help!

project.clj

(defproject test-midje "0.1.1"
  :description "Why doesn't midje work?"
  :min-lein-version "2.0.0"
  :source-paths ["src/clj"]
  :repl-options {
                 :timeout 120000
                 }
  :main org.midjetest.core
  :profiles {:dev {:dependencies [[midje "1.5.0"]]}}
  :aot [org.midjetest.core])

src/clj/org/midjetest/core.clj

(ns org.midjetest.core
  (:require [midje.sweet :refer [fact facts]]))


(defn addtwo [a] (+ 2 a))

(fact "addtwo adds two to numbers"
      (addtwo 3) => 5)


(defn -main
  "testing with main"
  ([] (println (addtwo 5))))

lein run or lein repl give the following error:

 $ lein repl
Compiling org.midjetest.core
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at clojure.lang.RT.loadClassForName(RT.java:2056)
at clojure.lang.RT.load(RT.java:419)
at clojure.lang.RT.load(RT.java:400)
at clojure.core$load$fn__4890.invoke(core.clj:5415)
at clojure.core$load.doInvoke(core.clj:5414)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5227)
at clojure.core$load_lib.doInvoke(core.clj:5264)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:603)
at clojure.core$load_libs.doInvoke(core.clj:5298)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:603)
at clojure.core$require.doInvoke(core.clj:5381)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at org.midjetest.core$loading__4784__auto__.invoke(core.clj:1)
at org.midjetest.core__init.load(Unknown Source)
at org.midjetest.core__init.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at clojure.lang.RT.loadClassForName(RT.java:2056)
at clojure.lang.RT.load(RT.java:419)
at clojure.lang.RT.load(RT.java:400)
at clojure.core$load$fn__4890.invoke(core.clj:5415)
at clojure.core$load.doInvoke(core.clj:5414)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5227)
at clojure.core$load_lib.doInvoke(core.clj:5264)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:603)
at clojure.core$load_libs.doInvoke(core.clj:5298)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:603)
at clojure.core$require.doInvoke(core.clj:5381)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at user$eval5.invoke(form-init9180276290836069038.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6511)
at clojure.lang.Compiler.eval(Compiler.java:6500)
at clojure.lang.Compiler.eval(Compiler.java:6500)
at clojure.lang.Compiler.load(Compiler.java:6952)
at clojure.lang.Compiler.loadFile(Compiler.java:6912)
at clojure.main$load_script.invoke(main.clj:283)
at clojure.main$init_opt.invoke(main.clj:288)
at clojure.main$initialize.invoke(main.clj:316)
at clojure.main$null_opt.invoke(main.clj:349)
at clojure.main$main.doInvoke(main.clj:427)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Caused by: java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.hash(ConcurrentHashMap.java:333)
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:988)
at clojure.lang.Namespace.find(Namespace.java:188)
at clojure.core$find_ns.invoke(core.clj:3659)
at clojure.core$the_ns.invoke(core.clj:3691)
at clojure.core$ns_name.invoke(core.clj:3698)
at midje.Bootstrap$bootstrap.invoke(Bootstrap.clj:8)
at midje.sweet__init.load(Unknown Source)
at midje.sweet__init.<clinit>(Unknown Source)
... 53 more
Exception in thread "Thread-4" clojure.lang.ExceptionInfo: Subprocess failed {:exit-code 1}
at clojure.core$ex_info.invoke(core.clj:4327)
at leiningen.core.eval$fn__3532.invoke(eval.clj:226)
at clojure.lang.MultiFn.invoke(MultiFn.java:231)
at leiningen.core.eval$eval_in_project.invoke(eval.clj:326)
at clojure.lang.AFn.applyToHelper(AFn.java:167)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.core$apply.invoke(core.clj:619)
at leiningen.repl$server$fn__7443.invoke(repl.clj:201)
at clojure.lang.AFn.applyToHelper(AFn.java:159)
at clojure.lang.AFn.applyTo(AFn.java:151)
at clojure.core$apply.invoke(core.clj:617)
at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1788)
at clojure.lang.RestFn.invoke(RestFn.java:425)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.RestFn.applyTo(RestFn.java:132)
at clojure.core$apply.invoke(core.clj:621)
at clojure.core$bound_fn_STAR_$fn__4102.doInvoke(core.clj:1810)
at clojure.lang.RestFn.invoke(RestFn.java:397)
at clojure.lang.AFn.run(AFn.java:24)
at java.lang.Thread.run(Thread.java:744)

Source: (StackOverflow)

For loop not working inside midje test?

Found some odd behavior in midje, not sure if it's midje related, or due to my misunderstanding of some clojure constructs, but it's puzzling:

Inside a facts statement, a for loop is not getting called:

(ns t1
  (:require [midje.sweet :refer :all ] )
  )

(facts
 (println "ok") ; -- this prints fine
 (for [val '(1 2 3)] (println val)) ; this does not

  (fact "junk"
        (> (.length "aaaaha") 3) => true ))

Thought maybe it had something to do with the for being overwritten in the ns but calling clojure.core/for behaves similarly.


Source: (StackOverflow)

Lein Midje :autotest throwing exception (No namespace found)

I am trying to setup autotest for midje. Currently, running lein midje works. However running lein midje :autottest gives me the stack trace below.

I run through my different namespaces and they all compile

Compiling 1 source files to /Users/oloo/Documents/work/cmp/target/classes

warning: Supported source version 'RELEASE_6' from annotation processor 'org.sonatype.guice.bean.scanners.index.SisuIndexAPT6' less than -source '1.7'
1 warning

======================================================================
Loading (cmp.models cmp.util cmp.repository.orderdeliveryschedule-repository cmp.repository.facility-repository cmp.repository.facility-cycle-data-repository cmp.views.layout cmp.routes.facility cmp.repository.item-repository cmp.repository.procurement-plan-repository cmp.routes.login cmp.excel-util cmp.repository.district-repository cmp.repository.facility-order-repository cmp.repository.facility-issue-repository cmp.routes.import-data cmp.test-util cmp.routes.item cmp.routes.district cmp.repository.user-repository cmp.routes.reports cmp.repository.category-repository cmp.routes.facility-issue cmp.routes.procurement-plan cmp.routes.facility-order cmp.handler cmp.repl cmp.repository.level-repository)
log4j:WARN No appenders could be found for logger (com.mchange.v2.log.MLog).
log4j:WARN Please initialize the log4j system properly.
Exception in thread "main" java.lang.Exception: No namespace: cmp.routes.item found
    at clojure.core$the_ns.invoke(core.clj:3760) 
    at clojure.core$ns_name.invoke(core.clj:3767)  
    at midje.repl$on_require_failure.invoke(repl.clj:387)  
    at midje.data.project_state$require_namespaces_BANG_$broken_source_file_QMARK___5874.invoke(project_state.clj:65)  
    at midje.data.project_state$require_namespaces_BANG_$shorten_ns_list_by_trying_first__5877.invoke(project_state.clj:69)  
    at midje.data.project_state$require_namespaces_BANG_.invoke(project_state.clj:75)  
    at midje.data.project_state$react_to_tracker_BANG_$fn__5889.invoke(project_state.clj:98)  
    at midje.repl$namespace_stream_checker.invoke(repl.clj:403)  
    at midje.data.project_state$react_to_tracker_BANG_.invoke(project_state.clj:94)  
    at midje.data.project_state$mkfn_COLON_scan_and_react$fn__5893$fn__5894.invoke(project_state.clj:109)  
    at clojure.lang.Atom.swap(Atom.java:37)  
    at clojure.core$swap_BANG_.invoke(core.clj:2160)  
    at midje.data.project_state$mkfn_COLON_scan_and_react$fn__5893.invoke(project_state.clj:107)  
    at midje.data.project_state$load_everything.invoke(project_state.clj:117)  
    at midje.repl$autotest.doInvoke(repl.clj:511)  
    at clojure.lang.RestFn.invoke(RestFn.java:397)  
    at midje.repl$autotest.doInvoke(repl.clj:524)  
    at clojure.lang.RestFn.invoke(RestFn.java:408)  
    at user$eval6032.invoke(NO_SOURCE_FILE:1)
    at clojure.lang.Compiler.eval(Compiler.java:6619)  
    at clojure.lang.Compiler.eval(Compiler.java:6609)  
    at clojure.lang.Compiler.eval(Compiler.java:6582)  
    at clojure.core$eval.invoke(core.clj:2852)  
    at clojure.main$eval_opt.invoke(main.clj:308)  
    at clojure.main$initialize.invoke(main.clj:327)  
    at clojure.main$null_opt.invoke(main.clj:362)  
    at clojure.main$main.doInvoke(main.clj:440)  
    at clojure.lang.RestFn.invoke(RestFn.java:421)  
    at clojure.lang.Var.invoke(Var.java:419)  
    at clojure.lang.AFn.applyToHelper(AFn.java:163)  
    at clojure.lang.Var.applyTo(Var.java:532)  
    at clojure.main.main(main.java:37)  
Subprocess failed

Source: (StackOverflow)

Redefining a macro operation with Clojure + Midje

Background

I'm new to Clojure so please forgive any glaring errors. I am trying to test some Clojure data access code that uses the redis-clojure library. Whilst my integration tests will, of course, test the full stack I do not want my unit tests to be reliant upon connecting to a redis server instance. Mocking the actual Redis commands with Midje appears to be relatively straight-forward however, the connection macro is more difficult to deal with.

Suggestions needed

What can't seem to do or find via the Midje documentation is way of mocking the redis connection or redefining the macro. The relevant top level connection macro from core.clj is:

(defmacro with-server
  "Evaluates body in the context of a connection to Redis server
  specified by server-spec.

  server-spec is a map with any of the following keys:
    :host     (\"127.0.0.1\")
    :port     (6379)
    :db       (0)
    :timeout  (5000)
    :password (nil)"
  ([server-spec & body]
     `(with-connection connection# *pool* ~server-spec
        (binding [redis.vars/*channel* (make-direct-channel connection#)]
          ~@body))))

(original code in context here)

I don't appear to be able to redefine the macro in my test code and wrapping the macro in a function doesn't get me any further forwards as I still need the body to be executed to produce my result. What I'd ideally like to do is execute the body passed into the connection macro and discard the rest of the macro. Any ideas?


Source: (StackOverflow)

Midje on travis-ci fails with NoSuchMethodError: KeywordLookupSite.

I'm trying to use the Midje testing framework for Clojure on the Travis CI service.

The project.clj looks like this:

(defproject my-project "0.1.0-SNAPSHOT"
  :description "Example"
  :dependencies [[org.clojure/clojure "1.3.0"]]
  :dev-dependencies [[midje "1.3.0"]
                     [lein-midje "1.0.7"]])

I added a .travis.yml file:

language: clojure
script: "lein midje"

Running lein midje locally (Ubuntu 11.10) works fine, but on Travis CI the build fails with the following exception:

Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite.<init>(ILclojure/lang/Keyword;)V
at clojure.lang.Util.runtimeException(Util.java:165)
at clojure.lang.Compiler.eval(Compiler.java:6476)
at clojure.lang.Compiler.eval(Compiler.java:6431)
at clojure.core$eval.invoke(core.clj:2795)
at clojure.main$eval_opt.invoke(main.clj:296)
at clojure.main$initialize.invoke(main.clj:315)
at clojure.main$script_opt.invoke(main.clj:339)
at clojure.main$main.doInvoke(main.clj:426)
at clojure.lang.RestFn.invoke(RestFn.java:482)
at clojure.lang.Var.invoke(Var.java:417)
at clojure.lang.AFn.applyToHelper(AFn.java:178)
at clojure.lang.Var.applyTo(Var.java:518)
at clojure.main.main(main.java:37)
Caused by: java.lang.NoSuchMethodError: clojure.lang.KeywordLookupSite.<init>(ILclojure/lang/Keyword;)V
at leiningen.util.paths$native_arch_path.<clinit>(paths.clj:32)
at leiningen.util.paths__init.load(Unknown Source)
at leiningen.util.paths__init.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at clojure.lang.RT.loadClassForName(RT.java:2030)
at clojure.lang.RT.load(RT.java:417)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5200)
at clojure.core$load_lib.doInvoke(core.clj:5237)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$load_libs.doInvoke(core.clj:5271)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$require.doInvoke(core.clj:5352)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at leiningen.core$loading__4414__auto__.invoke(core.clj:1)
at leiningen.core__init.load(Unknown Source)
at leiningen.core__init.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at clojure.lang.RT.loadClassForName(RT.java:2030)
at clojure.lang.RT.load(RT.java:417)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)
at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5200)
at clojure.core$load_lib.doInvoke(core.clj:5237)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$load_libs.doInvoke(core.clj:5271)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:604)
at clojure.core$use.doInvoke(core.clj:5363)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at user$eval1.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6465)
... 11 more

Why does the error occur on Travis CI, but not my machine? What can I do to fix this?


Source: (StackOverflow)

Why can't I use midge to mock a function that throws using slingshot's throw+

Here's the situation: I'm trying to unit test function A that calls function B. Function B is called in a slingshot try+ block and under certain circumstances it can throw using a slingshot throw+. I want to mock function B in a midje test so that it returns something that the catch in the try+ block will actually catch. I can't seem to create the right thing to throw though. Here's a substantially abbreviated sketch of the code and the test:

(defn function-A
  [param]
  (try+
    (function-B param)
    (catch [:type :user-not-found]
      (do-something))))

(defn function-B
  [param]
  (throw+ [:type :user-not-found]))

(fact "do-something is called"
  (function-A "param") => (whatever is the result of calling do-something)
  (provided
    (function-B "param") =throws=> (clojure.lang.ExceptionInfo. "throw+: {:type :user-not-found}"
                                                                {:object {:type :user-not-found}, :environment {}}
                                                                nil)))

The ExceptionInfo that I'm throwing seems to be roughtly the right thing. I can see this when my application is running through numerous prn statements. However, whatever I try, I can't get the test to work.

I also tried the bit of code below in a repl to see whether I could understand the problem. However, whilst both pieces of code seem to involve identical Exceptions, only one (the pure slingshot one) manages to catch and print "caught it". I think that if I could understand why one works and the other doesn't, I would be able to solve the problem with the unit test.

(try+
  (try
    (throw+ {:type :user-not-found})
    (catch Exception e
      (prn "Caught:  " e)
      (prn "Class:   " (.getClass e))
      (prn "Message: " (.getMessage e))
      (prn "Cause:   " (.getCause e))
      (prn "Data:    " (.getData e))
      (throw e)))
  (catch [:type :user-not-found] p
    (prn "caught it")))

(try+
  (try
    (throw (clojure.lang.ExceptionInfo. "throw+: {:type :user-not-found}"
                                        {:object {:type :user-not-found}, :environment {}}
                                        nil))
    (catch Exception e
      (prn "Caught:  " e)
      (prn "Class:   " (.getClass e))
      (prn "Message: " (.getMessage e))
      (prn "Cause:   " (.getCause e))
      (prn "Data:    " (.getData e))
      (throw e)))
  (catch [:type :user-not-found] p
    (prn "caught it")))

Source: (StackOverflow)

leiningen midje tests not working in Intellij

Consider the following (minimal) leiningen project

./project.clj:

(defproject repro "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [midje               "1.5.1"]])

./repro/src/repro/core.clj:

(ns repro.core)

./repro/test/repro/core_test.clj:

(ns repro.core-test
  (:require [repro.core  :refer :all]
            [midje.sweet :refer :all]))

(facts "about numbers"
       (fact "trivial"
         1 => 1) )

If I have the leiningen midje plugin installed, this runs at the command prompt as follows:

lein clean
lein midje
~~> All checks (1) succeeded.

However, if I import the leiningen project into Intellij 12.1.5 Community Edition, I get a fat stack trace:

Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
    ...
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.hash(ConcurrentHashMap.java:333)
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:988)
at clojure.lang.Namespace.find(Namespace.java:188)
at clojure.core$find_ns.invoke(core.clj:3728)
at clojure.core$the_ns.invoke(core.clj:3760)
at clojure.core$ns_name.invoke(core.clj:3767)
at midje.Bootstrap$bootstrap.invoke(Bootstrap.clj:8)
at midje.sweet__init.load(Unknown Source)
at midje.sweet__init.<clinit>(Unknown Source)
... 37 more

Looks like La Clojure + Intellij can't find some of midje's prerequisites, which is odd, because La Clojure is running classpaths out of the leiningen .m2 directory.

I've looked for a midje plugin for Intellij, but no luck so far.

I need this because although I am happy to use just emacs + leiningen, my team wants Intellij.


Source: (StackOverflow)

Passing data to a liberator post endpoint in midje test using ring-mock

I am trying to write a midje test using ring-mock to do a post to a liberator endpoint. I can successfully write a test for get requests but I can't seem to pass data to the post, I only get back the malformed response. Here is the meat of the code that I have.

;; ====
; Resource
;; ====
(def users (atom [{:id 1 :name "User One"} {:id 2 :name "User Two"}]))

(defn malformed-users? [context]
  (let [params (get-in context [:request :multipart-params])]
    (and
      (empty? (get params "id"))
      (= (get-in context [:request :request-method]) :post))))

(defresource all-users []
  :allowed-methods [:get :post]
  :available-media-types ["application/json"]
  :handle-ok (fn [_] {:users @users})
  :malformed? (fn [context] (malformed-users? context))
  :handle-malformed "You need to pass both a valid name and id"
  :post! (fn [context]
           (let [params (get-in context [:request :multipart-params])]
             (swap! users conj {:id (bigint (get params "id")) :name (get params "name")})))
  :handle-created (fn [_] {:users @users}))

(defroutes user-routes
  (ANY "/users" [_] (all-users)))


;; ====
; Test
;; ====
(fact "Get request to users endpoint returns desired content"
  (let [response (user-routes (mock/request :post "/users" {:id "3" :name "TestGuy"}))]
    (:status response) => 201
    (get-in response [:headers "Content-Type"]) => "application/json;charset=UTF-8"))

Source: (StackOverflow)

Midje, provided not working as I expect

I have written the following Midje test:

(fact (followers-minus-friends ...name...) => ["Dude"]
      (provided (idset show-followers ...name...) => #{1 2 3}
                (idset show-friends ...name...) => #{1 2}
                (userinfos #{3}) => [{:screen_name "Dude"}]))

to test the following function (in a different namespace):

(defn followers-minus-friends [screenname]
  (let [difference-ids (difference (idset show-followers screenname)
                                   (idset show-friends screenname))
        userinfos (userinfos difference-ids)]
    (map :screen_name userinfos)))

The test may seem pretty useless, but I'm just trying to get accustomed to Midje. Somehow, the function idset just gets executed, which I wanted to prevent by providing a return value in the provided-clause. What could be an explanation for this?

EDIT: I have uploaded the project to Github here, in case you want to try to reproduce the above situation: https://github.com/Borkdude/twitter-utils


Source: (StackOverflow)

Faking friend credential function using Midje

I'm trying to test my routing in isolation using Midje. For some routes that hit the database I have no trouble using (provided ...) to isolate the route from a real db call. I've introduced Friend for authentication and I've been unable to fake the call to the credential function.

My credential function looks like this (It's implemented like this because I don't want it getting called just yet):

(defn cred-fn
  [creds]
  (println (str "hey look I got called with " creds))
  (throw (Exception.)))

The middleware for the routes then look like this:

(def app 
  (-> app-routes
      (wrap-json-body {:keywords? true :bigdecimals? true})
      wrap-json-response
      (wrap-defaults defaults)
      (friend/authenticate
       {:unauthorized-handler json-auth/login-failed
        :workflows [(json-auth/json-login
                     :login-uri "/login"
                     :login-failure-handler json-auth/login-failed
                     :credential-fn auth/cred-fn)]})
      (ring-session/wrap-session)))

I've also tried without using the auth-json-workflow, the implementation for the routes looks almost identical and I can add that if it helps but I get the same result.

And then my tests look like this (using ring-mock):

(defn post [url body]
  (-> (mock/request :post url body)
      (mock/content-type "application/json")
      app))

(fact "login with incorrect username and password returns unauthenticated"
  (:status (post "/login" invalid-auth-account-json)) => 401
  (provided
    (auth/cred-fn anything) => nil))
(fact "login with correct username and password returns success"
  (:status (post "/login" auth-account-json)) => 200
  (provided
    (auth/cred-fn anything) => {:identity "root"}))

I then get the following output running the tests:

hey look I got called with {:password "admin_password", :username "not-a-user"}
FAIL at (handler.clj:66)
These calls were not made the right number of times:
    (auth/cred-fn anything) [expected at least once, actually never called]
FAIL "routes - authenticated routes - login with incorrect username and password returns unauthenticated" at (handler.clj:64)
    Expected: 401
      Actual: java.lang.Exception
          clojure_api_seed.authentication$cred_fn.invoke(authentication.clj:23)

hey look I got called with {:password "admin_password", :username "root"}
FAIL at (handler.clj:70)
These calls were not made the right number of times:
    (auth/cred-fn anything) [expected at least once, actually never called]

FAIL "routes - authenticated routes - login with correct username and password returns success" at (handler.clj:68)
    Expected: 200
      Actual: java.lang.Exception
          clojure_api_seed.authentication$cred_fn.invoke(authentication.clj:23)

So from what I can see the provided statement is not taking effect, and I'm not sure why. Any ideas?


Source: (StackOverflow)

How do I test futures in clojure?

I'm trying to use midje to test a future, but I can't seem to get it to work.

The code looks like

(defn foo []
  (let [f (future (bar))]
    (baz @f))

With a test like

(fact 
  (foo) => ..a..
  (provided
    (bar) => ..b..
    (baz ..b..) => ..a..))

This fails, saying that bar never gets called. Any way around this?


Source: (StackOverflow)