persistent-mtl-0.1.0.1: Monad transformer for the persistent API
Safe HaskellNone
LanguageHaskell2010

Database.Persist.Monad.TestUtils

Description

Defines MockSqlQueryT, which one can use in tests in order to mock out persistent database queries called in production code.

Synopsis

Documentation

data MockSqlQueryT m a Source #

A monad transformer for testing functions that use MonadSqlQuery.

Instances

Instances details
Monad m => Monad (MockSqlQueryT m) Source # 
Instance details

Defined in Database.Persist.Monad.TestUtils

Methods

(>>=) :: MockSqlQueryT m a -> (a -> MockSqlQueryT m b) -> MockSqlQueryT m b #

(>>) :: MockSqlQueryT m a -> MockSqlQueryT m b -> MockSqlQueryT m b #

return :: a -> MockSqlQueryT m a #

Functor m => Functor (MockSqlQueryT m) Source # 
Instance details

Defined in Database.Persist.Monad.TestUtils

Methods

fmap :: (a -> b) -> MockSqlQueryT m a -> MockSqlQueryT m b #

(<$) :: a -> MockSqlQueryT m b -> MockSqlQueryT m a #

Applicative m => Applicative (MockSqlQueryT m) Source # 
Instance details

Defined in Database.Persist.Monad.TestUtils

Methods

pure :: a -> MockSqlQueryT m a #

(<*>) :: MockSqlQueryT m (a -> b) -> MockSqlQueryT m a -> MockSqlQueryT m b #

liftA2 :: (a -> b -> c) -> MockSqlQueryT m a -> MockSqlQueryT m b -> MockSqlQueryT m c #

(*>) :: MockSqlQueryT m a -> MockSqlQueryT m b -> MockSqlQueryT m b #

(<*) :: MockSqlQueryT m a -> MockSqlQueryT m b -> MockSqlQueryT m a #

MonadIO m => MonadIO (MockSqlQueryT m) Source # 
Instance details

Defined in Database.Persist.Monad.TestUtils

Methods

liftIO :: IO a -> MockSqlQueryT m a #

MonadResource m => MonadResource (MockSqlQueryT m) Source # 
Instance details

Defined in Database.Persist.Monad.TestUtils

MonadIO m => MonadSqlQuery (MockSqlQueryT m) Source # 
Instance details

Defined in Database.Persist.Monad.TestUtils

runMockSqlQueryT :: MockSqlQueryT m a -> [MockQuery] -> m a Source #

Runs a MockSqlQueryT monad transformer using the given mocks.

When a database query is executed, the first mock that returns a Just is returned. If no mocks match the query, an error is thrown. See SqlQueryRep for the constructors available to match against. Most of the time, you'll want to use withRecord to only match queries against a specific record type (e.g. only match selectList calls for the Person entity).

Usage:

myFunction :: MonadSqlQuery m => m [String]
myFunction = map personName $ selectList [PersonAge >. 25] []

let persons = [Person ...]
result <- runMockSqlQueryT myFunction
  [ withRecord @Person $ \case
      SelectList _ _ -> Just persons
      _ -> Nothing
  , withRecord @Post $ \case
      Insert Post{ name = "post1" } -> Just $ toSqlKey 1
      _ -> Nothing
  , mockQuery $ \case
      RawExecuteCount "DELETE FROM person WHERE name = 'Alice'" [] -> Just 1
      _ -> Nothing
  ]

withRecord :: forall record. Typeable record => (forall a. SqlQueryRep record a -> Maybe a) -> MockQuery Source #

A helper for defining a mocked database query against a specific record type. Designed to be used with TypeApplications.

Most SqlQueryRep constructors are in the context of a specific record type, like Person. This helper only matches mocked database queries that are querying the record you specify.

Some constructors reference multiple record types, like BelongsTo. Look at the type to see the record you need to match against. For example,

withRecord @(Person, Post) $ \case
  BelongsTo _ _ -> ...

would match the function call

belongsTo :: (Person -> Maybe (Key Post)) -> Person -> SqlQueryRep (Person, Post) (Maybe Post)

mockQuery :: (forall record a. Typeable record => SqlQueryRep record a -> Maybe a) -> MockQuery Source #

A helper for defining a mocked database query.

This does not do any matching on the record type, so it is mostly useful for queries that don't use the record type, like rawExecute.

data MockQuery Source #

A mocked query to use in runMockSqlQueryT.

Use withRecord or another helper to create a MockQuery.

Specialized helpers

mockSelectSource :: forall record. Typeable record => ([Filter record] -> [SelectOpt record] -> Maybe [Entity record]) -> MockQuery Source #

A helper for mocking a selectSource or selectSourceRes call.

Usage:

mockSelectSource $ \filters opts ->
  if null filters && null opts
    then
      let person1 = [Entity (toSqlKey 1) $ Person "Alice"]
          person2 = [Entity (toSqlKey 2) $ Person "Bob"]
      in Just [person1, person2]
    else Nothing

mockSelectKeys :: forall record. Typeable record => ([Filter record] -> [SelectOpt record] -> Maybe [Key record]) -> MockQuery Source #

A helper for mocking a selectKeys or selectKeysRes call.

Usage:

mockSelectKeys $ \filters opts ->
  if null filters && null opts
    then Just $ map toSqlKey [1, 2]
    else Nothing

mockWithRawQuery :: (Text -> [PersistValue] -> Maybe [[PersistValue]]) -> MockQuery Source #

A helper for mocking a withRawQuery call.

Usage:

mockWithRawQuery $ \sql vals ->
  if sql == "SELECT id, name FROM person"
    then
      let row1 = [toPersistValue 1, toPersistValue "Alice"]
          row2 = [toPersistValue 2, toPersistValue "Bob"]
      in Just [row1, row2]
    else Nothing

mockRawQuery :: (Text -> [PersistValue] -> Maybe [[PersistValue]]) -> MockQuery Source #

A helper for mocking a rawQuery or rawQueryRes call.

Usage:

mockRawQuery $ \sql vals ->
  if sql == "SELECT id, name FROM person"
    then
      let row1 = [toPersistValue 1, toPersistValue "Alice"]
          row2 = [toPersistValue 2, toPersistValue "Bob"]
      in Just [row1, row2]
    else Nothing

mockRawSql :: (Text -> [PersistValue] -> Maybe [[PersistValue]]) -> MockQuery Source #

A helper for mocking a rawSql call.

Usage:

mockRawSql $ \sql vals ->
  if sql == "SELECT id, name FROM person"
    then
      let row1 = [toPersistValue 1, toPersistValue "Alice"]
          row2 = [toPersistValue 2, toPersistValue "Bob"]
      in Just [row1, row2]
    else Nothing