使用Hspec单元测试IO操作 [英] Unit testing IO actions with Hspec

查看:128
本文介绍了使用Hspec单元测试IO操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在类似的路线上发现了其他问题,但没有在这个特定情况下回答我的问题。此外,似乎只有很少的资源可以简洁地涵盖Haskell中单元测试IO操作的主题。



假设我有用于数据库通信的类型类型:

  data Something = Something String deriving Show 

class MonadIO m => MonadDB m其中
getSomething :: String - > m Something
getSomething s = do
... - 假定进行了一次数据库调用,并且另一个有效的函数

实例MonadDB IO

以及使用它的这个函数:

  getIt :: MonadDB m => m(Int,Something)
getIt = do $ b $ @(Something str)< - getSomethinghi
return(length str,s) - 请原谅例子

我想用hspec测试这个 getIt 函数,但没有它与数据库交谈,这大概意味着替换它使用的 MonadDB ,但我该如何实现这一目标?

解决方案

$ / $> $ / $> $!$ / $> $ / $> $ / $> $ b - stack exec --package transformers --package hspec - ghci
import Control.Monad.IO.Class
import Control.Monad.Trans.Identity

import Data.Char
import Test.Hspec

data Something = Something String推导(Eq,Show)

class MonadIO m => MonadDB m其中
getSomething :: String - > m Something
getSomething s = return $ Something(map toUpper s)

实例MonadDB IO

实例MonadIO m => MonadDB(IdentityT m)

getIt :: MonadDB m => m(Int,Something)
getIt = do $ b $ @(Something str)< - getSomethinghi
return(length str,s)

main: :IO()
main = hspec $ do
描述一些测试$ do
它test getIt$ do
runIdentityT getIt`shouldReturn`(2,SomethingHI )

ittest get it should fail$ do
runIdentityT getIt`shouldReturn`(1,SomethingHI)

您也可以使用 ReaderT StateT 到提供数据或转换为 getSomething 以在测试查询时使用。



编辑:使用示例在hspec内。


I have found other questions on similar lines but nothing that answers my question in this particular scenario. Furthermore, there seem to be few resources which succinctly cover the subject of unit testing IO actions in Haskell.

Let's say I have this typeclass for my database communication:

data Something = Something String deriving Show

class MonadIO m => MonadDB m where
  getSomething :: String -> m Something
  getSomething s = do
    ... -- assume a DB call is made and an otherwise valid function

instance MonadDB IO 

and this function which uses it:

getIt :: MonadDB m => m (Int, Something)
getIt = do
  s@(Something str) <- getSomething "hi"
  return (length str, s) -- excuse the contrived example

I wish to test this getIt function with hspec but without it talking to the database, which presumably means replacing which MonadDB it uses, but how do I achieve that?

解决方案

Would this work for you?

#!/usr/bin/env stack
-- stack exec --package transformers --package hspec -- ghci
import Control.Monad.IO.Class
import Control.Monad.Trans.Identity

import Data.Char
import Test.Hspec

data Something = Something String deriving (Eq, Show)

class MonadIO m => MonadDB m where
  getSomething :: String -> m Something
  getSomething s = return $ Something (map toUpper s)

instance MonadDB IO

instance MonadIO m => MonadDB (IdentityT m)

getIt :: MonadDB m => m (Int, Something)
getIt = do
  s@(Something str) <- getSomething "hi"
  return (length str, s)

main :: IO ()
main = hspec $ do
  describe "Some tests" $ do
    it "test getIt" $ do
      runIdentityT getIt `shouldReturn` (2, Something "HI")

    it "test getIt should fail" $ do
      runIdentityT getIt `shouldReturn` (1, Something "HI")

You might also be able to use ReaderT or StateT to "supply" data or a transformation for getSomething to use upon test querying.

Edit: Example use from within hspec.

这篇关于使用Hspec单元测试IO操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆