我刚完成Clojure的前六个星期,到目前为止,我对这种语言非常满意。我正在用leiningen和PostgreSQL开发个人博客。我已经可以发布新内容,上传文件,并且拥有会话,Cookie和角色,无论如何,我认为此时我已经有足够的代码来开始担心测试部分,但是由于看起来很多Clojure的测试和规范方面正在发生一些事情。
所以我有这个功能:
(defn download
"GET /admin/uploads/download/:id"
[params]
(let [id (-> params :id)
upload (model-upload/get-upload id)
filename (:filename upload)
body (clojure.java.io/file (str "public/uploads/" filename))]
{:status 200
:body body
:headers {"Content-Type" "application/pdf"
"Content-Length" (str (.length body))
"Cache-Control" "no-cache"
"Content-Disposition" (str "attachment; filename=" filename)}}))
该函数以映射作为参数,并传递最终映射以由compojure发送和处理。我来自Rails世界,因此在Rails中测试此功能的方法是创建一个FactoryGirl类,并使用经典的方法创建Rspec模型文件:
expect(first_map).to eq(map_returned_by_function)
在其中比较期望值,然后从命令行运行rspec以获得绿线或红线。
自昨天以来,我正尝试使用此文档使用Clojure复制该过程:
https://www.codesai.com/2018/03/kata-generating-bingo-cards
但是我认为还没有一种“标准”的方法来进行测试,包括Clojure中的DB(CRUD)部分。我什至不知道将规范文件放在哪里。我看到了类似于FactoryGirl的Clojure库,但是我不知道是否应该使用spec创建自己的数据结构,因此我不确定从哪里开始,这里有clojure.test.check.generators和spec生成器,但是我不知道知道它们是否不同,或者我应该只使用spec而不使用clojure.test.check。我可以从命令行而不是在REPL内部运行测试吗?
我的意思是:是否有有关如何测试一组CRUD功能的文档或教程?我想我只需要最初的HOWTO,然后就可以从那儿取下来,我将为像我这样的新手编写一个教程。
已更新:
似乎我要寻找Midje:
https://github.com/marick/Midje/wiki/A-tutorial-introduction
答案 0 :(得分:2)
在Clojure中,惯常做法是将IO推送到应用程序的边缘。您无需从下载功能内部的数据库中读取数据,而是将从数据库读取的数据传递至参数映射中的下载功能中。然后,您针对纯部分编写测试。
您的函数最终看起来像这样:
(defn download-without-db
"GET /admin/uploads/download/:id"
[params]
(let [upload (-> params :upload)
filename (:filename upload)
body (clojure.java.io/file (str "public/uploads/" filename))]
{:status 200
:body body
:headers {"Content-Type" "application/pdf"
"Content-Length" (str (.length body))
"Cache-Control" "no-cache"
"Content-Disposition" (str "attachment; filename=" filename)}}))
(defn get-upload-from-db [params]
(assoc params :upload (-> params :id model-upload/get-upload)))
(defn download [params]
(-> params
get-upload-from-db
download-without-db))
答案 1 :(得分:1)
您只是在寻找clojure.test。甚至在其文档中提到了与RSpec的关系。
这是Clojure本身的一部分,不需要依赖,并且我建议您在使用非标准测试框架(如Midje)之前先熟悉它,因为它是Clojure的事实上的测试框架,并且最受欢迎的一个。
您可以这样编写测试:
(deftest download
(testing "With valid input"
(testing "it should return a header map with filename included"
(is (= first_map (unit/download {:id 1}))))))
现在,Clojure不是面向对象的,因此没有要模拟的对象。也就是说,您经常在Clojure中使用Java表单,而Java提供了类和对象。如果要轻松模拟它们,可以使用名为Mockito的Java模拟框架。
在您的情况下,download
函数不使用任何Java对象。所以您也不需要。
现在,如果您希望将其作为集成测试,那么我编写的测试对您已经足够了。如果您希望这是一个单元测试,并且我假设(model-upload/get-upload id)
做了一些IO,那么您将想模拟model-upload/get-upload
函数。您可以使用with-redefs-fn轻松做到这一点:
(deftest download
(testing "With valid input"
(testing "it should return a header map with filename included"
(with-redefs-fn {#'model-upload/get-upload (constantly {:filename "cool.pdf"})}
(is (= first_map (unit/download {:id 1})))))))
或者您可以使用with-redefs:
(deftest download
(with-redefs [model-upload/get-upload (constantly {:filename "cool.pdf"})]
(testing "With valid input"
(testing "it should return a header map with filename included"
(is (= first_map (unit/download {:id 1})))))))
答案 2 :(得分:0)