Open eigenhombre opened 9 years ago
Usually I've used around
for this, something like
(ns myapp.test
(:require [speclj.core :refer :all]))
(def db "database-a")
(describe "db"
(around [it] (with-redefs [db "database-b"] (it)))
(it "should be called database-b"
(should= db "database-b")))
Not sure why the difference between lein spec -a
and lein spec
, or if this gets rid of the problem completely, but that's at least a workaround in case you're not familiar with around
.
I wonder if this could have to do with Speclj internally requiring a different version of Clojure when run with the vigilant runner than with the standard, so that, when lein spec
is run, certain forms do nothing when rebound with with-redefs
and require binding
instead.
@trptcolin thanks for the suggestion. That works; however, the following does not:
(ns myapp.test
(:require [myapp.test :refer :all]
[speclj.core :refer :all]))
(def db "database-a")
(defmacro describe-with-db [text & body]
`(describe ~text
(around [it] (with-redefs [db "database-b"] (it)))
~@body))
(describe-with-db "db"
(it "should be called database-b"
(should= db "database-b")))
Throws
1) java.lang.RuntimeException: Can't use qualified name as parameter: speclj.core/it, compiling:(myapp/test.clj:20:1) [...]
-- this more closely matches what we want to do (dry out DB mocking to use an in-memory test DB rather than a "real" one).
Any suggestions (I know you know one or two things about macros AND speclj :-) )? Thanks in advance!
@eigenhombre I believe this is solved by changing db
in your with-redefs
with #'db
(which is short-hand for (var-get db)
).
@sdegutis It's complaining about it
, not db
... it looks like one of the macros is expanding into (let [it ...] ...)
which wants a gensym inside the (remaining) macro.
@eigenhombre Yep! it
-> it#
(auto-gensym), as below:
(ns myapp.test
(:require [myapp.test :refer :all]
[speclj.core :refer :all]))
(def db "database-a")
(defmacro describe-with-db [text & body]
`(describe ~text
(around [it#] (with-redefs [db "database-b"] (it#)))
~@body))
(describe-with-db "db"
(it "should be called database-b"
(should= db "database-b")))
Does that do the trick for you?
@trptcolin works for our minimal test case -- trying it in our app. I also called it foo#
instead of it#
and that also worked. So I guess the name is just a temporarily alias for all the forms in the body?
Yep, inside around
, it
(or whatever you name it) is just a function that represents all the tests to be executed inside that describe
/context
.
@trptcolin We're unblocked -- that worked for us. I guess there's still the open question of why this is only needed with lein spec
and not lein spec -a
-- anyways, thanks for the help!
I'm running into the same issue. It seems to be a difference between the standard runner and the vigilant runner.
Using around
works, but I'm also curious why the runners are treating with-redefs
differently.
lein spec
andlein spec -a
treat the following differently; the test fails in the former, and passes in the latter.In general, we find that running
lein spec
requireswith-redefs
to be specified withinit
blocks (andlein spec -a
doesn't), making it harder to mock out e.g. a database connection for a whole set of tests. Can this be improved somehow?