请在2024 Clojure状态调查中分享您的想法!

欢迎!请查看关于页面以了解更多关于如何使用本网站的信息。

+1投票
其他

在我的应用程序中,我想模拟REST调用可能返回的每一种可能的响应。这不仅是为了测试,也是为了在运行应用程序时演示不同行为。
例如,我有一个需求,我的前端要对其后端执行健康检查,如果健康检查失败,则显示一条消息,说明没有可用服务。我现在想要一个始终失败的健康检查模拟,以便我可以演示该消息。
我想到了三种方法。

  1. 协议
  2. 不同的源路径
  3. 高阶函数

有人对这些中的任何一个有经验吗?如果有,每种方法的优缺点是什么?我遗漏了什么吗?

2个回答

+1投票

您尝试以这样一种方式来组合应用程序,即模拟很少需要,也就是说,您的函数大多数都是纯净的。

就您的案例而言,这意味着您会得到一个对象,代表失败,并使该函数(直接或间接)显示一条消息。

首先,最好是这样的函数:获取一个失败对象,返回一个效果(或分发一个事件)。

现在您不需要模拟任何东西,只需要运行一个测试,使用常规健康检查结果和一个失败结果,并检查结果。

还有一个神奇的宏with-redef,它允许您临时重新绑定项。
在这个例子中,http/post已被重新定义

(deftest is-a-macro
  (with-redefs [http/post (fn [url] {:body "Goodbye world"})]
    (is (= {:body "Goodbye world"} (http/post "http://service.com/greet")))))

通常这就可以了。
您当然可以使用各种Java模拟库,但我发现我很少需要它们。

by
小心,`with-redefs` 不是线程安全的。如果同时运行你的测试,你会得到疯狂的结果 :)
0
by

在特别替代函数 M 的情况下,Mocking 函数 M 是测试函数 A,你认为 A 会调用函数 M?

但这并不十分优雅,认为 A 会调用 M。相反,如果 A 调用了足以值得 Mock 的某些功能,将 M 作为参数传递给 A。(换句话说,将 A 调用的函数作为 A 的一个参数。)使特性显式可替代。

使用 Stuart Sierra 的 "component" 或应用类似纪律,以一种狡黠、不引人注目、灵活的方式连接程序的功能,如您的互联网案例,这是一种类似于 "依赖注入" 的行为。在测试中注入模拟互联网,在正常模式下注入真实互联网。

...