fakepull
Monad to pull from fake stream-like objects.
Example
Sometimes you might want to test a function that uses an HTTP client object to
get responses from some web server, without actually making the HTTP requests.
import Control.Monad.IO.Class
import Data.IORef
import Data.Maybe
import Test.Hspec
import Test.Pull.Fake.IO
data Request = Request
{ searchTerm :: String
, pageSize :: Int
, cursor :: Maybe String
} deriving (Eq, Show)
data Response = Response
{ searchResult :: [String]
, nextCursor :: Maybe String
} deriving (Eq, Show)
fetchAllPages :: MonadIO m => (Request -> m Response) -> String -> m [String]
fetchAllPages sendRequest term = go [] (Request term 3 Nothing)
where
go accum req = do
res <- sendRequest req
let newAccum = accum ++ searchResult res
case nextCursor res of
Just cur -> do
let newReq = req { cursor = Just cur }
go newAccum newReq
Nothing -> return newAccum
sendRequestActually :: Request -> IO Response
sendRequestActually = error "This function should be stubbed!"
stubbedSendRequest :: FakeStream Response -> Request -> IO Response
stubbedSendRequest stream _request =
fromJust <$> pull stream
main :: IO ()
main = hspec $
describe "fetchAllPages" $
it "collect all results by sending requests" $ do
let allResponses =
[ Response ["result 1-1", "result 1-2", "result 1-3"] $ Just "cursor a"
, Response ["result 2-2", "result 2-2", "result 2-3"] $ Just "cursor b"
, Response ["result 3-1"] Nothing
]
responsesToReturn <- newFakeStream allResponses
fetchAllPages (stubbedSendRequest responsesToReturn) "result"
`shouldReturn` concatMap searchResult allResponses
Related package
- fakefs
- This package is a variant of fakefs for stream-like objects.