如何在Clojure中模拟文件读取

时间:2019-08-02 22:29:54

标签: clojure

我有以下代码从我的资源文件夹加载edn数据:

(defn load-data
  []
  (->> (io/resource "news.edn")
       slurp
       edn/read-string))

我想通过模拟文件读取部分来对此进行测试,到目前为止,我已经拥有了:

(deftest loading-data
  (is (= (edn/read-string (prn-str {:articles [{:title "ASAP Rocky released" :url "http://foo.com"}]})) (load-data))))

但是我知道这个测试很不稳定,因为如果edn文件名更改,内容或更新,则测试将失败。有什么想法吗?

4 个答案:

答案 0 :(得分:4)

您想对此功能有什么信心?您是否担心news.edn不存在?您是否担心在某项资源上大吃大喝和/或edn阅读不起作用?

我的建议是分别测试您单独的问题

如果您担心news.edn不存在断言它的存在

如果您担心该功能的其余部分无法从edn转换,请添加新的签名以接受资源,然后在测试时提供另一个资源以对此进行断言

如果您担心文件的形状,则可以在将数据放入news.edn之前进行针对数据的测试。

然后,几年后再回到这些测试时,您会看到失败的明确原因,而不是因为在调试之前未知的N个可能原因而导致测试失败的原因

答案 1 :(得分:3)

您可以使用with-redefs模拟出对函数的调用,即“在执行主体时临时重新定义Vars”。例如,

(deftest load-data-test
  (with-redefs [slurp (constantly "{:a \"b\"}")]
    (is (= (load-data) {:a "b"}))))

这样,slurp范围内load-data中的with-redefs返回"{:a \"b\"}"

答案 2 :(得分:1)

正如其他人所建议的那样:模拟更少的事情。

这可能是您从构建Java测试中学到的。

如果您正确构造了函数,则可以单独进行测试,而无需产生副作用(例如读取文件)。

如果在示例中模拟slurp,则说明您没有测试任何有意义的东西:实际上,您将测试标准函数edn/read-string是否按预期工作。

答案 3 :(得分:1)

重写您的load-data以接受要加载的文件名作为参数(然后在您的“ main”中使用news.edn进行调用)。这使其功能更强大,并且您可以通过现在的测试方式轻松测试load-data,但是可以从测试资源中传递一些test-news.edn。无需为幸福的道路而嘲笑任何东西。

这样,您还可以针对其他情况编写测试:如果文件丢失,该怎么办?或.edn文件格式错误。如果您传递一些永久加载的资源怎么办?等