4

我使用Spockwreq在 Haskell 中编写了一个非常简单的应用程序。我想写一些测试,但我不知道该怎么做。

该应用程序所做的只是向另一台服务器发出 HTTP 请求,并将 JSON 响应转换为对人类友好的消息。如果有帮助,这里是代码。我想编写一个测试,在给定某个 JSON 响应的情况下断言人性化消息是正确的。

在 Ruby 中,我会模拟 HTTP 客户端,在这种情况下wreq,以控制我得到的 JSON 响应,但我不确定在 Haskell 中如何,甚至是否可以做到这一点。

根据我从研究中收集的信息,听起来类型类约束类型变量是要走的路,这对我来说就像依赖注入,但我不确定如何在 Spock 和wreq。

Spock 测试教程描述了如何在听起来很棒的水平上测试Spock IO Application。我不确定的部分是如何“注入”模拟 HTTP 客户端来控制 JSON 响应。

任何帮助表示赞赏!

4

1 回答 1

3

如果我们想支持不同的请求方法,我们必须对它们进行抽象。您可以让您的处理程序接受一个执行 HTTP 请求的函数作为参数,然后传递不同的函数进行测试和生产。如果您有多个相关功能,请将它们放在记录中(句柄模式)。


如果我们使用cabal-install > 2.0(使用new-* commands),另一个可能的选择是使用模块签名在测试套件和最终可执行应用程序之间切换实现。该解决方案还大量使用了 Cabal 的内部便利库功能。

基本思想是这样的:我们将Spock应用程序放在它自己的库中,但不要让它直接依赖wreq。相反,我们在同一个库中声明这样的签名Requests.hsig

signature SomeSpockApp.Requests where

import           Data.Aeson (FromJSON)

data Token

doGET :: FromJSON a => String -> Token -> IO a 

它定义了一个用于执行 HTTP 请求的高级接口。库中的代码将导入此签名。对于库中的其余代码,SomeSpockApp.Requests只是另一个模块。

接下来,我们定义一个便利库,它将提供一个实际的模块SomeSpockApp.Requests(与签名同名,只是现在它是一个hs文件)。它将包含“模拟”代码。当然,定义doGET必须与签名兼容。

SomeSpockApp.Requests我们还用另一个模块定义了另一个便利库。这个应该依赖于 wreq 并使用 wreq 的函数来完成我们签名的方法。

在测试套件中,我们应该同时依赖 Spock 应用程序库和模拟库。签名和模拟实现模块的名称完美对齐,因此无需再做任何事情。(如果名称不匹配,我们可以使用 cabal 文件中的mixins节来重命名模块)。

在应用程序可执行文件中,我们应该同时依赖 Spock 应用程序库和 wreq-using 库。

于 2018-08-26T21:25:12.020 回答