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