Check out Control.Proxy.Tutorial. If you can write a Proxy wrapper around your type, then you can easily swap out the test interface and a real interface like this:
client <-< simulatedServer
client <-< realServer
Edit: To answer your question in the comment, you use a Server
to write a wrapper around your simpleHTTP
requests:
realServer
:: HStream ty => Request ty -> Server (Request ty) (Result (Response ty)) IO r
realServer = foreverK $ \req -> do
result <- lift $ simpleHTTP req
respond result
The simulated server would look like:
simulatedServer
:: (Monad m, HStream ty)
=> Request ty -> Server (Request ty) (Result (Response ty)) m r
simulatedServer = foreverK $ \req -> do
result <- lift $ simulatedRequest req
respond result
And your client would look like:
client
:: (Monad m, HStream ty) => () -> Client (Request ty) (Result (Response ty)) m r
client () = forever $ do
let req = <something>
result <- request req
lift $ doSomethingWith result
Then you can test the real server and fake server using:
-- Test the real server
main = runSession $ client <-< realServer
-- Test the fake server
main = runSession $ client <-< simulatedServer
The client
and simulatedServer
are polymorphic in the base monad only because I don't know what base monad they would use for your testing. The only requirement is that the two things you compose have the same base monad or that at least one is polymorphic in the base monad.