首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HSpec中的多个前置函数?

HSpec中的多个前置函数?
EN

Stack Overflow用户
提问于 2017-12-16 16:37:53
回答 1查看 333关注 0票数 1

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

代码语言:javascript
复制
newEmptyRepository :: IO InMemoryGameRepository

其中InMemoryGameRepository的定义如下:

代码语言:javascript
复制
type State = (HashMap GameId Game)
type IORefState = IORef State
newtype InMemoryGameRepository = InMemoryGameRepository IORefState

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

代码语言:javascript
复制
spec =
  before app $ do
    describe "GET /" $ do
      it "responds with 200" $ get "/" `shouldRespondWith` 200
      it "responds with 'hello'" $ get "/" `shouldRespondWith` "hello"
    ...

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

代码语言:javascript
复制
app :: InMemoryGameRepository -> IO Application
app repo = scottyApp $ routes repo

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

代码语言:javascript
复制
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的定义如下:

代码语言:javascript
复制
startGame :: InMemoryGameRepository -> IO Game

在这里,编译器说明(显然) repo不在作用域内。但是我如何才能做到这一点呢?也就是说,我想在app和测试中共享一个newEmptyRepository实例。

Ps:你可以在github上看到完整的应用程序。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-19 00:29:29

应该使用beforeWith,它的类型为

代码语言:javascript
复制
beforeWith :: (b -> IO a) -> SpecWith a -> SpecWith b

例如,将其用作类型为SpecWith Application -> Specbefore newEmptyRepository . beforeWith app

如果您希望在测试用例中同时访问InMemoryGameRepositoryApplication,请定义一个帮助函数

代码语言:javascript
复制
withArg f a = (,) a <$> f a
withArg :: Functor f => (t -> f b) -> t -> f (t, b)

然后使用

代码语言:javascript
复制
before newEmptyRepository . beforeWith (withArg app)
    :: SpecWith (InMemoryGameRepository, Application) -> Spec

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

代码语言:javascript
复制
  before newEmptyRepository 
. beforeWith (withArg startGame) 
. beforeWith (withArg $ app . fst)
:: SpecWith ((InMemoryGameRepository, Game), Application) -> Spec
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47843958

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档