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

316 views Asked by At

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?

2

There are 2 answers

2
guilespi On BEST ANSWER

It really depends on your friend's auth workflow if authorized? will get called at all.

Also, I've never could get midje to do runtime mocking, so I usually mock functions using with-redefs

Something along these lines should work for you:

(fact "The users page can be fetched successfully"
      (let [req (request :get "/user")
            response (app req)]
        (with-redefs [friend/authorize (fn [roles f] f)]
          (:body response)) => #"(some results)"))
0
schaueho On

Turns out I was too optimistic about Midje's provided functionality. It's closely tied to one checkable, assuming that the mocked code is called in the course of the checkable. I.e. the following works now for me:

(fact "The users page can be fetched successfully" 
  (app (request :get "/user")) => (contains {:status 200}) 
  (provided 
     (friend/authorized? anything anything) => true))