clojure是否需要依赖注入才能使代码更易于测试?

Dan*_*lan 14 testing clojure

我记得读过一篇关于Ruby如何不真正需要DI或DI框架的文章,因为这些类是开放的.因此,您可以简单地重写依赖项的构造函数,以便它返回一个伪对象.

我是Clojure和函数式编程的新手.我想知道Clojure是否需要依赖注入,或者它可以出于类似/其他原因而放弃它.这是一个可以使用的具体示例(如何指出我的设计是非惯用的Clojure):

想象一下,你正在开发一个网络爬虫/蜘蛛.它需要遍历您下载的网页.这是一个带有副作用的动作.网页可能会在每个查询中发生变化,您的互联网连接可能会被删除等.它会找到网页上的所有链接,访问每个链接,然后以相同的方式遍历它.

现在,您想要编写一个模拟http客户端的测试,以便它返回一个硬编码的字符串响应.你如何-main在测试中调用该程序并阻止它使用真正的 http客户端?

quu*_*x00 16

with-redefsclojure.core中的宏对于截断函数非常有用.

这是一个简短的REPL会话来证明这一点:

user=> (defn crawl [url]
  #_=>   ;; would now make http connection and download content
  #_=>   "data from the cloud")
#'user/crawl
user=> (defn -main [& args]
  #_=>   (crawl "http://www.google.com"))
#'user/-main
user=> (-main)
"data from the cloud"
user=> (with-redefs [crawl (fn [url] "fake data")]
  #_=>   (-main))
"fake data"
Run Code Online (Sandbox Code Playgroud)

由于Clojure程序(大部分)由函数而不是对象组成,因此函数的动态重新绑定取代了DI框架为测试目的所做的大量工作.


mik*_*era 11

在Clojure中,您通常使用替代方法实现相当于依赖注入:

  • 动态绑定 - 例如,用于通过执行重定向测试功能中的标准输出(binding [*out* some-writer-object] ...)
  • 高阶函数 - 可以通过将其他函数作为参数传递来提供依赖注入的形式
  • 使用数据进行配置 - 在Clojure中传递包含配置参数(甚至是用于配置自定义行为的函数)的映射是相当惯用的.

所有这些都是语言本身的组成部分.所以你绝对不需要像"DI框架"那样的东西.恕我直言,需要DI的框架实际上只是补偿语言本身缺乏足够的功能.