-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A flexible mock framework for testing effectful code. -- -- HMock is a flexible mock framework for testing effectful code in -- Haskell. Tests can set up expectations about actions that can or -- should be performed and their results, and then verify those -- expectations when the test is complete. -- -- For more information, see the module documentation for -- Test.HMock. @package HMock @version 0.5.1.2 -- | Internal utilities used for HMock implementation. module Test.HMock.Internal.Util -- | A value together with its source location. data Located a Loc :: Maybe String -> a -> Located a -- | Annotates a value with its source location from the call stack. locate :: CallStack -> a -> Located a -- | Formats a Located String to include its source location. withLoc :: Located String -> String -- | Returns all ways to choose one element from a list, and the -- corresponding remaining list. choices :: [a] -> [(a, [a])] instance GHC.Base.Functor Test.HMock.Internal.Util.Located -- | Template Haskell utilities used to implement HMock. module Test.HMock.Internal.TH -- | Gets the unapplied top-level name from a type application. unappliedName :: Type -> Maybe Name -- | Fetches the Name of a TyVarBndr. tvName :: TyVarBndr flag -> Name -- | Creates a TyVarBndr for a plain variable without a kind -- annotation. bindVar :: Name -> TyVarBndr Specificity -- | Substitutes a Type for all occurrences of the given -- Name. substTypeVar :: Name -> Type -> Type -> Type -- | Makes variable substitutions from the given table. substTypeVars :: [(Name, Type)] -> Type -> Type -- | Splits a function type into a list of bound type vars, context, -- parameter types, and return value type. splitType :: Type -> ([Name], Cxt, [Type], Type) -- | Gets all free type variable Names in the given Type. freeTypeVars :: Type -> [Name] -- | Culls the given binders and constraints to choose only those that -- apply to free variables in the given type. relevantContext :: Type -> ([Name], Cxt) -> ([Name], Cxt) -- | Produces a CxtQ that gives all given variable Names all -- of the given class Types. constrainVars :: [TypeQ] -> [Name] -> CxtQ -- | Attempts to unify the given types by constructing a table of -- substitutions for the variables of the left type that obtain the right -- one. unifyTypes :: Type -> Type -> Q (Maybe [(Name, Type)]) -- | Removes all module names from Names in the given value, so that -- it will pretty-print more cleanly. removeModNames :: Data a => a -> a -- | Determines if this is a polytype, including top-level quantification. hasPolyType :: Type -> Bool -- | Determines if there is a polytype nested anywhere in the given type. -- Top-level quantification doesn't count. hasNestedPolyType :: Type -> Bool -- | Attempts to produce sufficient constraints for the given Type -- to be an instance of the given class Name. resolveInstance :: Name -> [Type] -> Q (Maybe Cxt) -- | Attempts to produce sufficient constraints for the given Type -- to be a satisfied constraint. The type should be a class applied to -- its type parameters. -- -- Unlike simplifyContext, this function always resolves the -- top-level constraint, and returns Nothing if it cannot do so. resolveInstanceType :: Type -> Q (Maybe Cxt) -- | Simplifies a context with complex types (requiring FlexibleContexts) -- to try to obtain one with all constraints applied to variables. -- -- Should return Nothing if and only if the simplified contraint is -- unsatisfiable, which is the case if and only if it contains a -- component with no type variables. simplifyContext :: Cxt -> Q (Maybe Cxt) -- | Remove instance context from a method. -- -- Some GHC versions report class members including the instance context -- (for example, show :: Show a => a -> String, instead of -- show :: a -> String). This looks for the instance context, -- and substitutes if needed to eliminate it. localizeMember :: Type -> Name -> Type -> Q Type -- | This module provides the basic vocabulary for talking about -- multiplicity, which is the number of times something is allowed to -- happen. Multiplicities can be any range of natural numbers, with or -- without an upper bound. module Test.HMock.Multiplicity -- | An acceptable range of number of times for something to happen. -- -- A multiplicity can have a lower and an upper bound. data Multiplicity -- | Checks whether a certain number satisfies the Multiplicity. meetsMultiplicity :: Multiplicity -> Int -> Bool -- | Checks whether a Multiplicity is capable of matching any number -- at all. -- --
-- >>> feasible once -- True -- -- >>> feasible 0 -- True -- -- >>> feasible (once - 2) -- False --feasible :: Multiplicity -> Bool -- | A Multiplicity that means exactly once. -- --
-- >>> meetsMultiplicity once 0 -- False -- -- >>> meetsMultiplicity once 1 -- True -- -- >>> meetsMultiplicity once 2 -- False --once :: Multiplicity -- | A Multiplicity that means any number of times. >>> -- meetsMultiplicity anyMultiplicity 0 True >>> -- meetsMultiplicity anyMultiplicity 1 True >>> -- meetsMultiplicity anyMultiplicity 10 True anyMultiplicity :: Multiplicity -- | A Multiplicity that means at least this many times. -- --
-- >>> meetsMultiplicity (atLeast 2) 1 -- False -- -- >>> meetsMultiplicity (atLeast 2) 2 -- True -- -- >>> meetsMultiplicity (atLeast 2) 3 -- True --atLeast :: Multiplicity -> Multiplicity -- | A Multiplicity that means at most this many times. -- --
-- >>> meetsMultiplicity (atMost 2) 1 -- True -- -- >>> meetsMultiplicity (atMost 2) 2 -- True -- -- >>> meetsMultiplicity (atMost 2) 3 -- False --atMost :: Multiplicity -> Multiplicity -- | A Multiplicity that means any number in this interval, -- endpoints included. For example, between 2 3 means 2 -- or 3 times, while between n n is equivalent to -- n. -- --
-- >>> meetsMultiplicity (between 2 3) 1 -- False -- -- >>> meetsMultiplicity (between 2 3) 2 -- True -- -- >>> meetsMultiplicity (between 2 3) 3 -- True -- -- >>> meetsMultiplicity (between 2 3) 4 -- False --between :: Multiplicity -> Multiplicity -> Multiplicity instance GHC.Classes.Eq Test.HMock.Multiplicity.Multiplicity instance GHC.Show.Show Test.HMock.Multiplicity.Multiplicity instance GHC.Num.Num Test.HMock.Multiplicity.Multiplicity -- | The internal core language of expectations in HMock. module Test.HMock.Internal.ExpectSet -- | A set of expected steps and their responses. This is the "core" -- language of expectations for HMock. It's based roughly on -- Svenningsson, Svensson, Smallbone, Arts, Norell, and Hughes' -- Expressive Semantics of Mocking. However, there are a few small -- adjustments. We have two repetition operators which respectively -- represent general repetition with interleaving, and consecutive -- repetition. We also attach arbitrary multiplicities to repetition. data ExpectSet step [ExpectStep] :: step -> ExpectSet step [ExpectNothing] :: ExpectSet step [ExpectSequence] :: ExpectSet step -> ExpectSet step -> ExpectSet step [ExpectInterleave] :: ExpectSet step -> ExpectSet step -> ExpectSet step [ExpectEither] :: ExpectSet step -> ExpectSet step -> ExpectSet step [ExpectMulti] :: Multiplicity -> ExpectSet step -> ExpectSet step [ExpectConsecutive] :: Multiplicity -> ExpectSet step -> ExpectSet step -- | Checks whether an ExpectSet is in an "accepting" state. In other -- words, is it okay for the test to end here? If False, then there are -- still expectations that must be satisfied before the test can succeed. satisfied :: ExpectSet step -> Bool -- | Computes the live steps of the ExpectSet. In other words: which -- individual steps can be matched right now, and what are the remaining -- expectations in each case? liveSteps :: ExpectSet step -> [(step, ExpectSet step)] -- | Performs a complete simplification of the ExpectSet. This could be -- slow, but we intend to do it only for error messages, so it need not -- be very fast. simplify :: ExpectSet step -> ExpectSet step -- | Get a list of all steps mentioned by an ExpectSet. This is used -- to determine which classes need to be initialized before adding an -- expectation. getSteps :: ExpectSet step -> [step] -- | A higher-level intermediate form of an ExpectSet suitable for -- communication with the user. Chains of binary operators are collected -- into sequences to be displayed in lists rather than arbitrary nesting. data CollectedSet step [CollectedStep] :: step -> CollectedSet step [CollectedNothing] :: CollectedSet step [CollectedSequence] :: [CollectedSet step] -> CollectedSet step [CollectedInterleave] :: [CollectedSet step] -> CollectedSet step [CollectedChoice] :: [CollectedSet step] -> CollectedSet step [CollectedMulti] :: Multiplicity -> CollectedSet step -> CollectedSet step [CollectedConsecutive] :: Multiplicity -> CollectedSet step -> CollectedSet step -- | Collects an ExpectSet into the intermediate form for display. It's -- assumed that the expression was simplified before this operation. collect :: ExpectSet step -> CollectedSet step -- | Converts a set of expectations into a string that summarizes them, -- with the given prefix (used to indent). formatExpectSet :: Show step => ExpectSet step -> String -- | Reduces a set of expectations to the minimum steps that would be -- required to satisfy the entire set. This weeds out unnecessary -- information before reporting that there were unmet expectations at the -- end of the test. excess :: ExpectSet step -> ExpectSet step instance GHC.Classes.Eq step => GHC.Classes.Eq (Test.HMock.Internal.ExpectSet.ExpectSet step) instance GHC.Show.Show step => GHC.Show.Show (Test.HMock.Internal.ExpectSet.ExpectSet step) -- | This module defines the Rule type, which describes a matcher -- for methods and a (possibly empty) list of responses to use for -- successive calls to matching methods. The Expectable type class -- generalizes Rule, so that you can specify a bare Matcher -- or Action in most situations where a Rule is needed but -- you don't want to provide a response. module Test.HMock.Rule -- | A rule for matching a method and responding to it when it matches. -- -- The method may be matched by providing either an Action to -- match exactly, or a Matcher. Exact matching is only available -- when all method arguments -- -- A Rule may have zero or more responses, which are attached -- using |-> and |=>. If there are no responses for a -- Rule, then there must be a default response for that action, -- and it is used. If more than one response is added, the rule will -- perform the responses in order, repeating the last response if there -- are additional matches. -- -- Example: -- --
-- expect $ -- GetLine_ anything -- |-> "hello" -- |=> (GetLine prompt) -> "The prompt was " ++ prompt -- |-> "quit" --data Rule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type) -- | Class for things that can be expected. This is includes Rules, -- but also bare Matchers and Actions with no explicit -- response. class Expectable cls name m r ex | ex -> cls name m r -- | Converts an expectable to a Rule that means the same thing. toRule :: Expectable cls name m r ex => ex -> Rule cls name m r -- | Attaches a return value to an expectation. This is more convenient -- than |=> in the common case where you just want to return a -- known result. e |-> r means the same thing as e -- |=> const (return r). (|->) :: (Monad m, Expectable cls name m r ex) => ex -> r -> Rule cls name m r infixl 1 |-> -- | Attaches a response to an expectation. This is a flexible response, -- which can look at arguments, do things in the base monad, set up more -- expectations, etc. A matching Action is passed to the response. (|=>) :: Expectable cls name m r ex => ex -> (Action cls name m r -> MockT m r) -> Rule cls name m r infixl 1 |=> -- | A way to match an entire action, using conditions that might depend on -- the relationship between arguments. data WholeMethodMatcher cls name m r [SuchThat] :: Matcher cls name m r -> (Action cls name m r -> Bool) -> WholeMethodMatcher cls name m r instance Test.HMock.Rule.Expectable cls name m r (Test.HMock.Internal.Rule.Rule cls name m r) instance Test.HMock.Rule.Expectable cls name m r (Test.HMock.Mockable.Matcher cls name m r) instance Test.HMock.Rule.Expectable cls name m r (Test.HMock.Internal.Rule.WholeMethodMatcher cls name m r) -- | This module defines the MockableBase and Mockable -- classes that are needed to use an MTL-style type class with -- MockT. You will typically derive MockableBase with -- Template Haskell, since it's mostly boilerplate. The Mockable -- class adds a customizable setup method which you can define yourself -- to add the right defaults for methods in the mocked class. module Test.HMock.Mockable -- | A class for Monad subclasses whose methods can be mocked. This -- class augments MockableBase with a setup method that is run -- before HMock touches the Monad subclass for the first time. The -- default implementation does nothing, but you can derive your own -- instances that add setup behavior. class MockableBase cls => Mockable (cls :: (Type -> Type) -> Constraint) -- | An action to run and set up defaults for this class. The action will -- be run before HMock touches the class, either to add expectations or -- to delegate a method. -- -- By default, unexpected actions throw errors, and actions with no -- explicit default always return the default value of their return type, -- or undefined if there is none. You can change this on a -- per-class or per-test basis. -- --
-- expect $ -- GetLine_ anything -- |-> "hello" -- |=> (GetLine prompt) -> "The prompt was " ++ prompt -- |-> "quit" --data Rule (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type) [:=>] :: WholeMethodMatcher cls name m r -> [Action cls name m r -> MockT m r] -> Rule cls name m r -- | This module defines the ExpectContext class, whose members -- provide the combinators for building the execution plan for your -- mocks. Notably, there is a MockT instance for -- ExpectContext, so you can use these combinators to add -- expectations inside your tests that run in MockT, as well as -- nesting them in other combinators. module Test.HMock.ExpectContext -- | All constraints needed to mock a method with the given class, name, -- base monad, and return type. type MockableMethod (cls :: (Type -> Type) -> Constraint) (name :: Symbol) (m :: Type -> Type) (r :: Type) = (Mockable cls, Typeable m, KnownSymbol name, Typeable r) -- | Type class for contexts in which one can build expectations. Notably, -- this includes MockT, which expects actions to be performed -- during a test. -- -- The methods of this class represent the user-facing API for build your -- execution plan for mocks. class ExpectContext (ctx :: (Type -> Type) -> Type -> Type) -- | Creates an expectation that an action is performed once per given -- response (or exactly once if there is no response). -- --
-- runMockT $ do -- expect $ -- ReadFile "foo.txt" -- |-> "lorem ipsum" -- |-> "oops, the file changed out from under me!" -- callCodeUnderTest ---- -- In this example, readFile must be called exactly twice by the -- tested code, and will return "lorem ipsum" the first time, but -- something different the second time. expect :: (ExpectContext ctx, HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable) => expectable -> ctx m () -- | Creates an expectation that an action is performed some number of -- times. -- --
-- runMockT $ do -- expect $ MakeList -- expectN (atLeast 2) $ -- CheckList "Cindy Lou Who" |-> Nice -- -- callCodeUnderTest --expectN :: (ExpectContext ctx, HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable) => Multiplicity -> expectable -> ctx m () -- | Specifies a response if a matching action is performed, but doesn't -- expect anything. This is equivalent to expectN -- anyMultiplicity, but shorter. -- -- In this example, the later use of expectAny overrides earlier -- uses, but only for calls that match its conditions. -- --
-- runMockT $ do -- expectAny $ -- ReadFile_ anything |-> "tlhIngan maH!" -- expectAny $ -- ReadFile "config.txt" |-> "lang: klingon" -- -- callCodeUnderTest --expectAny :: (ExpectContext ctx, HasCallStack, MonadIO m, MockableMethod cls name m r, Expectable cls name m r expectable) => expectable -> ctx m () -- | Creates a sequential expectation. Other actions can still happen -- during the sequence, but these specific expectations must be met in -- this order. -- --
-- inSequence -- [ expect $ MoveForward, -- expect $ TurnRight, -- expect $ MoveForward -- ] ---- -- Beware of using inSequence too often. It is appropriate when -- the property you are testing is that the order of effects is correct. -- If that's not the purpose of the test, consider adding several -- independent expectations, instead. This avoids over-asserting, and -- keeps your tests less brittle. inSequence :: (ExpectContext ctx, MonadIO m) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m () -- | Combines multiple expectations, which can occur in any order. Most of -- the time, you can achieve the same thing by expecting each separately, -- but this can be combined in compound expectations to describe more -- complex ordering constraints. -- -- If ambiguity checking is disabled, the choice is left-biased, so -- earlier options are preferred over ambiguous later options. -- --
-- inSequence -- [ inAnyOrder -- [ expect $ AdjustMirrors, -- expect $ FastenSeatBelt -- ], -- expect $ StartCar -- ] --inAnyOrder :: (ExpectContext ctx, MonadIO m) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m () -- | Combines multiple expectations, requiring exactly one of them to -- occur. If ambiguity checking is disabled, the choice is left-biased, -- so earlier options are preferred over ambiguous later options. -- --
-- anyOf -- [ expect $ ApplyForJob, -- expect $ ApplyForUniversity -- ] --anyOf :: (ExpectContext ctx, MonadIO m) => (forall ctx'. ExpectContext ctx' => [ctx' m ()]) -> ctx m () -- | Creates a parent expectation that the child expectation will happen a -- certain number of times. Unlike expectN, the child expectation -- can be arbitrarily complex and span multiple actions. Also unlike -- expectN, each new execution will restart response sequences for -- rules with more than one response. -- -- Different occurrences of the child can be interleaved. If ambiguity -- checking is disabled, progressing on an existing occurrence is -- preferred over starting a new occurrence when it's ambiguous. times :: (ExpectContext ctx, MonadIO m) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m () -- | Creates a parent expectation that the child expectation will happen a -- certain number of times. Unlike expectN, the child expectation -- can be arbitrarily complex and span multiple actions. Also unlike -- expectN, each new execution will restart response sequences for -- rules with more than one response. -- -- Different occurrences of the child must happen consecutively, with one -- finishing before the next begins. consecutiveTimes :: (ExpectContext ctx, MonadIO m) => Multiplicity -> (forall ctx'. ExpectContext ctx' => ctx' m ()) -> ctx m () -- | This module defines monads for working with mocks. HMock tests run in -- the MockT monad transformer. A more limited monad, -- MockSetup, is used for setting up defaults for each class. Both -- are instances of the MockContext monad, which defines a shared -- API. module Test.HMock.MockT -- | Monad transformer for running mocks. data MockT m a -- | Runs a test in the MockT monad, handling all of the mocks. runMockT :: forall m a. MonadIO m => MockT m a -> m a -- | Runs a test in the MockT monad. The test can unlift other MockT -- pieces to the base monad while still acting on the same set of -- expectations. This can be useful for testing concurrency or similar -- mechanisms. -- --
-- test = withMockT $ inMockT -> do -- expect $ ... -- -- liftIO $ forkIO $ inMockT firstThread -- liftIO $ forkIO $ inMockT secondThread ---- -- This is a low-level primitive. Consider using the unliftio -- package for higher level implementations of multithreading and other -- primitives. withMockT :: forall m b. MonadIO m => ((forall a. MockT m a -> m a) -> MockT m b) -> m b -- | Starts a nested block within MockT. The nested block has its -- own set of expectations, which must be fulfilled before the end of the -- block. -- -- Beware: use of nestMockT might signify that you are doing too -- much in a single test. Consider splitting large tests into a separate -- test for each case. nestMockT :: forall m a. MonadIO m => MockT m a -> MockT m a -- | Starts a nested block within MockT. The nested block has its -- own set of expectations, which must be fulfilled before the end of the -- block. It can unlift other MockT pieces to the base monad while still -- acting on the same set of expectations. This can be useful for testing -- concurrency or similar mechanisms. -- -- Beware: use of nestMockT might signify that you are doing too -- much in a single test. Consider splitting large tests into a separate -- test for each case. withNestedMockT :: forall m b. MonadIO m => ((forall a. MockT m a -> m a) -> MockT m b) -> MockT m b -- | The severity for a possible problem. data Severity -- | Fail the test. Error :: Severity -- | Print a message, but continue the test. Warning :: Severity -- | Don't do anything. Ignore :: Severity -- | Sets the severity for ambiguous actions. An ambiguous action is one -- that matches expectations in more than one way. If this is not set to -- Error, the most recently added expectation will take -- precedence. -- -- This defaults to Ignore. setAmbiguityCheck :: MonadIO m => Severity -> MockT m () -- | Sets the severity for uninteresting actions. An uninteresting action -- is one for which no expectations or other configuration have been -- added that mention the method at all. If this is not set to -- Error, then uninteresting methods are treated just like -- unexpected methods. -- -- Before you weaken this check, consider that the labeling of methods as -- "uninteresting" is non-compositional. A change in one part of your -- test can result in a formerly uninteresting action being considered -- interesting in a different part of the test. -- -- This defaults to Error. setUninterestingActionCheck :: MonadIO m => Severity -> MockT m () -- | Sets the severity for unexpected actions. An unexpected action is one -- that doesn't match any expectations *and* isn't explicitly allowed by -- allowUnexpected. If this is not set to Error, the action -- returns its default response. -- -- This defaults to Error. setUnexpectedActionCheck :: MonadIO m => Severity -> MockT m () -- | Sets the severity for unmet expectations. An unmet expectation happens -- when an expectation is added, but either the test (or nesting level) -- ends or verifyExpectations is used before a matching action -- takes place. -- -- This defaults to Error. setUnmetExpectationCheck :: MonadIO m => Severity -> MockT m () -- | Fetches a String that describes the current set of outstanding -- expectations. This is sometimes useful for debugging test code. The -- exact format is not specified. describeExpectations :: MonadIO m => MockT m String -- | Verifies that all mock expectations are satisfied. If there is a -- nested block in effect, only the expectations of that nested block are -- verified You normally don't need to do this, because it happens -- automatically at the end of your test or nested block. However, it's -- occasionally useful to check expectations early. -- -- Beware: use of verifyExpectations might signify that you are -- doing too much in a single test. Consider splitting large tests into a -- separate test for each case. verifyExpectations :: MonadIO m => MockT m () -- | Monad for setting up a mockable class. Note that even though the type -- looks that way, this is *not* a monad transformer. It's a very -- restricted environment that can only be used to set up defaults for a -- class. data MockSetup m a -- | This type class defines a shared API between the MockT and -- MockSetup monads. class MockContext ctx -- | Adds a handler for unexpected actions. Matching calls will not fail, -- but will use a default response instead. The rule passed in must have -- zero or one responses: if there is a response, -- allowUnexpected (m |=> r) is equivalent to -- allowUnexpected m >> byDefault (m -- |=> r). -- -- The difference between expectAny and allowUnexpected is -- subtle, but comes down to ambiguity: -- --
-- instance Mockable MyClass where -- setupMockable _ = ... --[mockEmptySetup] :: MakeMockableOptions -> Bool -- | Whether to derive instances of the class for MockT or not. -- Defaults to True. -- -- This option will cause a build error if some members of the class are -- unmockable or are not methods. In this case, you'll need to define -- this instance yourself, delegating the mockable methods as follows: -- --
-- instance MyClass (MockT m) where -- myMethod x y = mockMethod (MyMethod x y) -- ... --[mockDeriveForMockT] :: MakeMockableOptions -> Bool -- | Suffix to add to Action and Matcher names. Defaults to -- "". [mockSuffix] :: MakeMockableOptions -> String -- | Whether to warn about limitations of the generated mocks. This is -- mostly useful temporarily for finding out why generated code doesn't -- match your expectations. Defaults to False. [mockVerbose] :: MakeMockableOptions -> Bool -- | Defines all instances necessary to use HMock with the given type, -- using default options. The type should be a type class extending -- Monad, applied to zero or more type arguments. -- -- This defines all of the following instances, if necessary: -- --
-- class Monad m => MonadFilesystem m where -- readFile :: FilePath -> m String -- writeFile :: FilePath -> String -> m () ---- -- You can use HMock to test code using MonadFilesystem like -- this: -- --
-- copyFile :: MonadFilesystem m => FilePath -> FilePath -> m () -- copyFile a b = readFile a >>= writeFile b -- -- makeMockable [t|MonadFilesystem|] -- -- spec = describe "copyFile" $ -- it "reads a file and writes its contents to another file" $ -- runMockT $ do -- expect $ ReadFile "foo.txt" |-> "contents" -- expect $ WriteFile "bar.txt" "contents" |-> () -- copyFile "foo.txt" "bar.txt" ---- -- The Template Haskell splice, makeMockable, generates the -- boilerplate needed to use MonadFilesystem with HMock. You -- then use runMockT to begin a test with mocks, expect to -- set up your expected actions and responses, and finally execute your -- code. module Test.HMock