haskell - HSpec 中的多个 before 函数?

标签 haskell scotty hspec

我有一个内存存储库,可以通过调用此函数来创建:

newEmptyRepository :: IO InMemoryGameRepository

其中 InMemoryGameRepository 定义如下:

type State = (HashMap GameId Game)
type IORefState = IORef State
newtype InMemoryGameRepository = InMemoryGameRepository IORefState

在为我的 Scotty 应用程序编写测试时,我看到过使用此方法的示例:

spec =
  before app $ do
    describe "GET /" $ do
      it "responds with 200" $ get "/" `shouldRespondWith` 200
      it "responds with 'hello'" $ get "/" `shouldRespondWith` "hello"
    ...

这一切都很好,但我还需要以某种方式初始化 InMemoryGameRepository(通过调用 newEmptyRepository)并在我的测试中使用创建的实例。因此我将 app 更改为:

app :: InMemoryGameRepository -> IO Application
app repo = scottyApp $ routes repo

我正在尝试创建一个使用存储库和IO应用程序的测试,例如这样(不起作用):

spec = 
    before (do repo <- newEmptyRepository
               app repo) $ 
      -- API Tests
      describe "GET /api/games" $ 
        it "responds with " $ do
          liftIO $ startGame repo
          get "/api/games" `shouldRespondWith` singleGameResponse

其中 startGame 定义如下:

startGame :: InMemoryGameRepository -> IO Game

这里编译器(显然)说repo不在范围内。但我怎样才能做到这一点呢? IE。我想为 app 和测试共享一个 newEmptyRepository 实例?

Ps:完整申请可以在 github 上看到.

最佳答案

您应该使用beforeWith其类型为

beforeWith :: (b -> IO a) -> SpecWith a -> SpecWith b

将其用作例如在 newEmptyRepository 之前。 beforeWith app,其类型为 SpecWith Application -> Spec

如果您想在测试用例中访问 InMemoryGameRepositoryApplication,请定义一个辅助函数

withArg f a = (,) a <$> f a
withArg :: Functor f => (t -> f b) -> t -> f (t, b)

然后使用

before newEmptyRepository . beforeWith (withArg app)
    :: SpecWith (InMemoryGameRepository, Application) -> Spec

最后,您不应该在测试定义中使用 liftIO $ startGame repo - 每次构建测试树时都会运行 startGame (尽管这可能会导致实际上是你想要的,但似乎并非如此)。相反,如果您使用 before 系列函数,startGame 将在测试实际运行之前运行一次。您甚至可以使用与上述相同的技术访问 startGame 返回的 Game:

  before newEmptyRepository 
. beforeWith (withArg startGame) 
. beforeWith (withArg $ app . fst)
:: SpecWith ((InMemoryGameRepository, Game), Application) -> Spec

关于haskell - HSpec 中的多个 before 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47843958/

相关文章:

haskell - Aeson 或 Wai.JSON QuasiQuoter 的问题 -- 将 0.0 转换为 0

haskell - 上传包到hackages时没有生成haddock

data-structures - 是否有联合和相交 Haskell Prelude 实现?

haskell - 什么时候泛型函数不是泛型的?

haskell -斯科蒂 : Set custom headers (x-frame-options)

在 Haskell 中对惰性表达式中未定义的值进行单元测试

Haskell 惰性求值

haskell - <**> 是 <*> 的变体,参数颠倒了。 "reversed"是什么意思?

Haskell Scotty Webserver 发送文本响应

haskell - HSpec 无预期编译失败