I have a Yesod app with the type:
data App = App
{ appSettings :: AppSettings
, appStatic :: Static
, appConnPool :: ConnectionPool
, appHttpManager :: Manager
, appLogger :: Logger
, appStripe :: forall a. ((FromJSON (StripeReturn a)), Typeable (StripeReturn a))
=> StripeConfig
-> StripeRequest a
-> IO (Either StripeError (StripeReturn a))
}
and a helper function
stripe :: (FromJSON (StripeReturn a), Typeable (StripeReturn a))
=> StripeRequest a
-> Handler (Either StripeError (StripeReturn a))
stripe req = do
f <- appStripe <$> getYesod
c <- appStripeConfig . appSettings <$> getYesod
liftIO $ f c req
that is used in several handlers. (The appStripe
field of the App
is never referenced directly in any handlers.) In makeFoundation
, everything is as scaffolded, except that the appStripe
field is filled in with Web.Stripe.stripe
from the stripe-haskell
library.
In my tests, I would like to be able to mock the calls to Stripe, so I have the following function:
withStripeExpecting :: (FromJSON (StripeReturn a), Typeable (StripeReturn a))
=> StripeRequest a
-> Either StripeError (StripeReturn a)
-> YesodExample App ()
-> YesodExample App ()
withStripeExpecting _expectedReq res = withStateT $ \yed -> yed {yedSite = f (yedSite yed)}
where f app = app {appStripe = mock}
mock :: Typeable (StripeReturn b)
=> StripeConfig
-> StripeRequest b
-> IO (Either StripeError (StripeReturn b))
mock _ _actualReq = do
-- assert actualReq matches expectedReq (in IO???)
return $ case cast res of
Just a -> a
Nothing -> error "Stripe return types don’t match in mock."
which I use in test cases like:
spec :: Spec
spec = withApp $ do
describe "create" $ do
it "returns a 201" $ do
-- a bunch of set-up elided
withStripeExpecting stripeReq (Right stripeRes) $ do
requestWithSubject "auth0|fake" $ do
setMethod "POST"
setUrl $ SubscriptionPlansR walletId
setRequestBody encoded
addRequestHeader (H.hContentType, "application/json")
statusIs 201
which compiles and runs, but throws an error StripeError {errorType = InvalidRequest, errorMsg = "Invalid API Key provided: ", errorCode = Nothing, errorParam = Nothing, errorHTTP = Just UnAuthorized}
suggesting that it is running the real stripe IO action instead of the mock.
How do I change a field of the App
during a test so that it will be used by the handler under test?
Aucun commentaire:
Enregistrer un commentaire