【问题标题】:How do you mock file reading in Clojure你如何在 Clojure 中模拟文件读取
【发布时间】:2019-08-06 16:56:42
【问题描述】:

我有以下代码从我的资源文件夹中加载 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 文件名发生更改、内容或更新,测试将失败。有什么想法吗?

【问题讨论】:

  • 所有答案都很好,不知道该接受哪一个:-(
  • 您最初的问题是如何模拟文件读取,恕我直言,您应该接受一个说明如何进行一般模拟以及如何在您的情况下进行模拟的问题。但真正的答案是,你根本不应该这样做。

标签: clojure


【解决方案1】:

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

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

这样load-datawith-redefs范围内的slurp返回"{:a \"b\"}"

【讨论】:

    【解决方案2】:

    您希望对这个功能有什么信心?你担心 news.edn 不存在吗?您是否担心 slurping 和/或 edn 阅读对资源不起作用?

    我的建议是分别测试您的不同关注点

    如果你担心 news.edn 不存在,就反对它的存在

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

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

    然后当你多年后回到这些测试时,你会看到失败的明确原因,而不是因为 N 个可能的原因而失败的测试,直到调试时才知道

    【讨论】:

      【解决方案3】:

      正如其他人所建议的那样:少模拟一些东西。

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

      如果您正确组合了函数,则可以单独测试它们而无需副作用(例如读取文件)。

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

      【讨论】:

        【解决方案4】:

        重写您的load-data 以接受要加载的文件名作为参数(稍后在您的“main”中使用news.edn 调用它)。这使其功能更强大,这样您就可以轻松地测试load-data,就像您现在测试它的方式一样,但是您从测试资源中传递了一些test-news.edn。也没有必要为幸福的道路嘲笑任何事情。

        这样你也可以为其他场景编写测试:如果文件丢失了怎么办?或者 .edn 文件格式错误。如果你传递一些永远加载的资源怎么办?等等

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-04
          • 2011-12-07
          • 2022-01-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多