Haskell:如何测试使用wreq的Spock应用?

时间:2018-08-26 20:20:14

标签: haskell testing dependency-injection haskell-spock wreq

我使用Spockwreq在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响应。

感谢您的帮助!

1 个答案:

答案 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的库。