问题描述
我在类似的路线上发现了其他问题,但没有在这个特定情况下回答我的问题。此外,似乎只有很少的资源可以简洁地涵盖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操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!