我正在尝试编写一些单元测试,以测试一些数据库模型。
我希望我的第一个deftest函数能够获取插入用户的数据库生成的ID,并将其保存在某个位置,以便下一个deftest能够从数据库中获取该用户。
我以为我可以通过在第一个测试中使用def
来做到这一点,但是在第二个测试中,定义的var被视为Unbound Var。这是我的代码:
(deftest test-user->db
(testing "Adding a new user record to db"
(->> (user->db {:name "Bob"}) ;; returns a UUID ID
(def mock-user-id)) ;; binding it here
(is (uuid? mock-user-id)))) ;; this passes
(deftest test-db->user
(testing "Getting a user record from db"
(let [user (db->user mock-user-id)] ;; mock-user-id is unbound :-/
(is (instance? User user))
(is (contains? user :id))
(is (contains? user :name))
(is (= mock-user-id (:id user)))
(is (= "Bob" (:name user))))))
不幸的是,我找不到关于这种情况的任何资源。我只能以某种方式为每个deftest重设名称空间的全局变量?
答案 0 :(得分:1)
显然测试不一定按顺序运行:
(deftest a-test
(println "a")
(def inner "hello"))
(deftest b-test
(println "b")
(println "inner" inner))
Testing tic-tac-toe.core-test
b
inner #object[clojure.lang.Var$Unbound 0x37acbc9e Unbound: #'tic-tac-toe.core-test/inner]
a
Ran 2 tests containing 0 assertions.
0 failures, 0 errors.
=> {:test 2, :pass 0, :fail 0, :error 0, :type :summary}
请注意如何首先打印“ b”。这意味着您的var可能尚未按需要进行初始化。
我将通过声明mock-user-id
为顶层来解决此问题,然后在两个测试中都使用它,以使测试顺序无关紧要。如果您不希望在绝对需要之前对其进行初始化,则可以将其包装在delay
中:
; delay will delay initialization until it's first used
(def mock-user-id (delay (user->db {:name "Bob"})))
(deftest test-user->db
(testing "Adding a new user record to db"
(is (uuid? @mock-user-id)))) ; @ to force the delay to run its body the first time
(deftest test-db->user
(testing "Getting a user record from db"
(let [user (db->user @mock-user-id)] ;; mock-user-id is unbound :-/
(is (instance? User user))
(is (contains? user :id))
(is (contains? user :name))
(is (= @mock-user-id (:id user)))
(is (= "Bob" (:name user))))))
答案 1 :(得分:0)
我想补充一下@carcigenicate的答案,以防其他人偶然发现此主题并希望按顺序运行某些测试功能(因为默认情况下,它们不按顺序运行)。
在特定测试的ns中,创建一个名为test-ns-hook
的函数,并按照您希望它们运行的顺序来调用它们。如果在ns中定义了test-ns-hook,则测试运行程序将只运行该函数,而不是该ns中所有已定义的测试。
所以在我的问题中,我在文件末尾添加了此功能:
(defn test-ns-hook []
(test-user->db)
(test-db->user))
这可确保test-user->db
首先运行并完成,绑定变量,然后在绑定该变量的情况下运行test-db->user
。