我使用Spock和wreq在Haskell中编写了一个非常简单的应用程序。我想写一些测试,但是我不确定该怎么做。
应用程序要做的就是向另一个服务器发出HTTP请求,并将JSON响应转换为对人类友好的消息。如果有帮助,请访问the code。我想编写一个测试,断言在给定JSON响应的情况下对人类友好的消息是正确的。
在Ruby中,我将模拟HTTP客户端(在这种情况下为wreq
)来控制我收到的JSON响应,但是我不确定在Haskell中如何或什至不能这样做。
从我的研究中得出的结论来看,type-class-constrained type variables似乎是要走的路,这对我来说就像是依赖注入,但是我不确定如何在Spock的上下文中做到这一点。和wreq。
Spock testing tutorial描述了如何在IO Application
级别上测试Spock,这听起来不错。我不确定的部分是如何“注入”模拟HTTP客户端以控制JSON响应。
感谢您的帮助!
答案 0 :(得分:2)
如果我们想支持提出请求的不同方法,则必须对它们进行抽象。您可以使处理程序接受执行HTTP请求的函数作为参数,然后将不同的函数传递给测试和生产。如果您有多个相关功能,请将它们放入记录(handle pattern)中。
如果我们使用cabal-install> 2.0(带有new-* commands),另一个可能的选择是使用module signature在测试套件和最终的可执行应用程序之间切换实现。该解决方案还大量使用Cabal的internal convenience libraries功能。
基本思想是:我们将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的库。