smallseo.info

Midje

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

Midje's `with-state-changes` and function calls

The following code works (obviously):

(use [midje.sweet])

(with-state-changes [(before :contents (println "setup") :after (println "teardown"))]
  (fact "one" 
    (println "doing 1")
    1 => 1)
  (fact "two"
    (println "doing 2")
    (+ 1 1) => 2))

The output is the expected one:

setup
doing 1
doing 2
teardown

But I want to have my facts grouped in a separate function like so:

(defn my-facts []
  (fact "one" ...)
  (fact "two" ...)
  #_( ... ))

(with-state-changes [(before :contents (println "setup") :after (println "teardown"))]
  (my-facts))

This time, midje cannot execute the code, I get the following error:

Midje could not understand something you wrote: 
        Background prerequisites created by the wrapping version of
        `against-background` only affect nested facts. This one
        wraps no facts.

        Note: if you want to supply a background to all checks in a fact, 
        use the non-wrapping form. That is, instead of this:
            (fact 
              (against-background [(f 1) => 1] 
                (g 3 2 1) => 8 
                (h 1 2) => 7)) 
        ... use this:
            (fact 
              (g 3 2 1) => 8 
              (h 1 2) => 7 
              (against-background (f 1) => 1)) 

Is there any way to achieve my goal? I want to use midje's setup- and teardown facilities but still be able to have my facts be contained inside a separate fn.


Source: (StackOverflow)

Ignoring authentication in unit tests in Clojure web app using Friend?

I'm using friend for protecting some pages in my web application, which is working fine so far. I'm running into issues with my test code, though: I seem to be unable to work around the authentication mechanism or to mock out friend's authorize calls. Things I've tried so far:

  • wrapping the request with a map containing the authentication information
  • using midje/provided to mock away calls to friend/authorize

The first approach doesn't seem to work because I don't know for certain what I would need to add to the request and the second one doesn't seem to work because midje seems not to see the call to friend/authorize at all. The relevant fact looks like this:

(fact "The users page can be fetched successfully"
      (let [req (request :get "/user")
            response (app req)]
        (:body response) => #"(some results)"
        (provided 
          (friend/authorized? anything anything) => true)))

And this is the corresponding (running) compojure route:

(GET "/user" [] (friend/authorize #{::admin} users))

I basically macroexpand-ed the friend/authorize call in the midje fact, but still I get two FAILS on the fact due to the authorization. The tests ran successfully before adding the authorization, so it's really the friend authorization part I need to solve.

Are there any best practices do solve this?


Source: (StackOverflow)

I cannot run tests in clojure/midje

I run tests with:

lein midje :autotest

And I get error:

Exception in thread "main" java.lang.Exception: No namespace: sprint-is.json-export found

File is in: sprint-is/src/sprint_is/json_export.clj

It contains code:

(ns sprint-is.json-export)
(require [[noir.response :as response]])
(defn serialize [value] (response/json value))

It throws this error even when I don't have no test file. When I create test file, I get similar error:

No namespace: sprint-is.test.json-export found

Test is in: sprint-is/test/sprint_is/json_export.clj

And contains:

(ns sprint-is.test.json-export
    (:require [sprint-is.json-export :as json-export]))

(fact "module can serialize scalar values"
    (json-export/serialize 123) => 123)

When I try to import it from REPL, it cannot find the namespaces too. I tried to rename file, move files, rename directories, remove ns (it compiles but it doesn't work), asked on Clojure IRC. I compared the code with other projects (including those working on my computer) and it seems same.

Source code is here: https://bitbucket.org/jiriknesl/sprintis


Source: (StackOverflow)

Stub out internal function calls in Midje

I'm testing a function that uses two other functions from other namespace.

(fact "a test"
      (let [result (function-that-uses-functions-from-other-namespace)]
      result => truthy))

I want to stub out the functions from other namespace and I'm having problems writing the test.

(fact "a test"
      (let [result (function-that-uses-functions-from-other-namespace)]
          (function-that-uses-functions-from-other-namespace)
          (provided (other-namespace/function1 "parameter") => "stub_response"))

but this approach don't seem to work. Any hints? Is it simply the case of let being evaluated before checkables as suggested in Using midje provided in a let clause doesn't stub methods


Source: (StackOverflow)

Midje Project.clj giving error

I'm seeing an error on my ring server which I start with lein with-profile dev ring server

java.io.FileNotFoundException: Could not locate midje/sweet__init.class or midje/sweet.clj on classpath: , compiling:(news/routes/headlines_test.clj:1:1)
...

Here's my project.clj:

(defproject news "0.1.0-SNAPSHOT"
  :description "..."
  :url "https://herokuapp.com"
  :min-lein-version "2.0.0"

  :ring {:handler news.core.handler/app
         :init    news.core.handler/init}

  :dependencies [[org.clojure/clojure   "1.6.0"]
                 [compojure             "1.3.1"]
                 [ring/ring-defaults    "0.1.3"]
                 [liberator             "0.11.0"]
                 [cheshire              "5.3.1"]
                 [org.clojure/java.jdbc "0.3.6"]
                 [postgresql/postgresql "9.3-1102.jdbc41"]
                 [yesql                 "0.5.0-rc1"]
                 [environ               "1.0.0"]]

  :plugins [[lein-ring    "0.9.1"]
            [lein-environ "1.0.0"]]

  :profiles {:dev-default  {:dependencies [[ring/ring-devel           "1.3.1"]]}
             :test-default {:dependencies [[midje                     "1.6.3"]
                                          [javax.servlet/servlet-api  "2.5"]
                                          [ring-mock                  "0.1.5"]]
                            :plugins      [[lein-midje                "3.1.3"]]}
             :production-default {:ring {:open-browser? false
                                         :stacktraces?  false
                                         :auto-reload?  false}}

             ;; Set these in ./profiles.clj
             :dev-env-vars  {}
             :test-env-vars {}

             :dev  [:dev-default  :dev-env-vars]
             :test [:test-default :test-env-vars]
             :production [:production-default] })

I guess my confusion is: Why am I getting an error about midje when I'm running the server in the dev environment?


Source: (StackOverflow)

Midje provided not stubbing function in Compojure / Ring handler

I'm attempting to use Midje to stub the view in a handler unit test, but my use of Midje's (provided) obviously isn't correct.

I've simplified and inlined the view to a (content) function in the handler:

(ns whattodo.handler
  (:use compojure.core)
  (:require [whattodo.views :as views]))

(defn content [] (views/index))

(defn index [] (content))

(defroutes app
  (GET "/" [] (index)))

and am trying to test it using

(ns whattodo.t-handler
  (:use midje.sweet)
  (:use ring.mock.request)
  (:use whattodo.handler))

(facts "It returns response"
       (let [response (app (request :get "/"))]
         (fact "renders index view" (:body response) => "fake-html"
               (provided (#'whattodo.handler/content) => (fn [] "fake-html")))))

I was expecting the stubbed function to be called returning 'fake-html' and thus the unit test passing, but instead, the test fails as the real implementation is called - invoking the real view.


Source: (StackOverflow)

Setup and teardown temporary directory for a midje fact

This is the skeleton of what I want to achieve

(let [temp-dir (create-temp-dir)]          ; setup
  (fact
    (do-something-with temp-dir) => true)  ; actual test
  (delete-dir temp-dir))                   ; teardown

The midje testing framework gives access to lexical scope (scroll down towards the end). So this is what I'd expect to work:

(against-background
  (around :facts
    (let [temp-dir (create-temp-dir)]
      (do ?form (delete-dir temp-dir))))
  (fact (do-something-with temp-dir) => true))

But the compiler complains that it can't resolve the symbol temp-dir. Any idea how to make this work?


Source: (StackOverflow)

Testing filesystem code

Unit-testing with Midje is a great experience, but now I need to test some code which interacts with the filessytem. Specifically, the code builds a data structure representation from a local directory layout.

Something that comes to mind is creating directories and files in /tmp, which then have to be cleaned up after the tests. I probably could make it work but it would be much better if there were a Right Way to do it.

What is the preferred way to test filesystem code, in Clojure or more generally?


Source: (StackOverflow)

Midje print stacktrace when test fails

I am learning Clojure, and trying to use TDD to do so *.

I use midje as a testing library. Love it so far, the expected versus actual results display is very helpfull.

But is there was a way to use clojure.tools.trace or something similar to print the trace of the first test that fails ?

*: Specifically, I remember seeing a talk by Robert C. Martin about the transformation priority premise, and I'm implementing a factorial function this way. There isn't yet much code to show though.


Source: (StackOverflow)

Dynamically calculated description of a midje fact

I want to write a function to factor out some common facts, like this

(defn check-odd-and-positive
  [n]
  (fact (str n " not odd") n => odd?)
  (fact (str n " not positive") n => positive?))

(facts "about the answer"
  (check-odd-and-positive 42))

But it doesn't result in "42 not odd" as the description of the fact. I know a similar effect could be achieved with tabular facts, but I want to be able to share such a fact among fact groups.


Source: (StackOverflow)

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))))

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)

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)

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)

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)