{-# LANGUAGE BlockArguments #-} {-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -Wno-type-defaults #-} {-# OPTIONS_GHC -Wno-unused-do-bind #-} {- HLINT ignore "Use newtype instead of data" -} module Test.MockCat.ShouldBeCalledSpec (spec) where import Control.Exception (ErrorCall(..), evaluate) import Data.List (isInfixOf) import Test.Hspec import Test.MockCat import Test.MockCat.Verify (verificationFailureMessage) import Prelude hiding (any) spec :: Spec spec = do describe "shouldBeCalled API" do describe "Simple verification (arguments only, at least once)" do it "single argument" do f <- mock $ "a" ~> True evaluate $ f "a" f `shouldBeCalled` "a" it "multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" f `shouldBeCalled` ("a" ~> "b") it "failure case" do f <- mock $ "a" ~> True evaluate $ f "a" f `shouldBeCalled` "b" `shouldThrow` anyErrorCall it "single argument with param" do f <- mock $ "a" ~> True evaluate $ f "a" f `shouldBeCalled` param "a" it "single argument with any" do f <- mock $ any ~> True evaluate $ f "a" f `shouldBeCalled` any it "single argument with expect" do f <- mock $ any ~> True evaluate $ f "a" f `shouldBeCalled` expect (const True) "always true" describe "Simple verification without arguments (anything)" do it "success" do f <- mock $ any ~> True evaluate $ f "a" f `shouldBeCalled` anything it "failure (never called)" do f <- mock $ "a" ~> True f `shouldBeCalled` anything `shouldThrow` anyErrorCall describe "Count verification with arguments" do it "times - exact count" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (times 3 `withArgs` "a") it "times - failure" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (times 3 `withArgs` "a") `shouldThrow` anyErrorCall it "atLeast - success" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (atLeast 3 `withArgs` "a") it "atLeast - failure" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (atLeast 3 `withArgs` "a") `shouldThrow` anyErrorCall it "atMost - success" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (atMost 3 `withArgs` "a") it "atMost - failure" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (atMost 2 `withArgs` "a") `shouldThrow` anyErrorCall it "greaterThan - success" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (greaterThan 2 `withArgs` "a") it "greaterThan - failure" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (greaterThan 2 `withArgs` "a") `shouldThrow` anyErrorCall it "lessThan - success" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (lessThan 4 `withArgs` "a") it "lessThan - failure" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (lessThan 3 `withArgs` "a") `shouldThrow` anyErrorCall it "once - success" do f <- mock $ "a" ~> True evaluate $ f "a" f `shouldBeCalled` (once `withArgs` "a") it "once - failure" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (once `withArgs` "a") `shouldThrow` anyErrorCall it "never - success" do f <- mock $ "a" ~> True f `shouldBeCalled` (never `withArgs` "a") it "never - failure" do f <- mock $ "a" ~> True evaluate $ f "a" f `shouldBeCalled` (never `withArgs` "a") `shouldThrow` anyErrorCall describe "Count verification with Param arguments" do it "times with param" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (times 3 `withArgs` param "a") it "times with any" do f <- mock $ any ~> True evaluate $ f "a" evaluate $ f "b" evaluate $ f "c" f `shouldBeCalled` (times 3 `withArgs` any) it "times with expect" do f <- mock $ any ~> True evaluate $ f "a" evaluate $ f "b" evaluate $ f "c" f `shouldBeCalled` (times 3 `withArgs` expect (const True) "always true") describe "Count verification without arguments (times only)" do it "times - success" do f <- mock $ any ~> True evaluate $ f "a" evaluate $ f "b" evaluate $ f "c" f `shouldBeCalled` times 3 it "times - failure" do f <- mock $ any ~> True evaluate $ f "a" evaluate $ f "b" f `shouldBeCalled` times 3 `shouldThrow` anyErrorCall describe "Order verification" do it "inOrderWith - success" do f <- mock $ any ~> () evaluate $ f "a" evaluate $ f "b" evaluate $ f "c" f `shouldBeCalled` inOrderWith ["a", "b", "c"] it "inOrderWith - failure" do f <- mock $ any ~> () evaluate $ f "a" evaluate $ f "b" evaluate $ f "c" f `shouldBeCalled` inOrderWith ["a", "b", "b"] `shouldThrow` anyErrorCall it "inPartialOrderWith - success" do f <- mock $ any ~> () evaluate $ f "a" evaluate $ f "b" evaluate $ f "c" f `shouldBeCalled` inPartialOrderWith ["a", "c"] it "inPartialOrderWith - failure" do f <- mock $ any ~> () evaluate $ f "b" evaluate $ f "a" f `shouldBeCalled` inPartialOrderWith ["a", "b"] `shouldThrow` anyErrorCall describe "Monadic mocks" do it "shouldBeCalled with IO mock" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) f `shouldBeCalled` ("a" ~> (1 :: Int)) it "shouldBeCalled times with IO mock" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) f `shouldBeCalled` (times 3 `withArgs` ("a" ~> (1 :: Int))) it "shouldBeCalled inOrderWith with IO mock" do f <- mock $ any ~> any ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "b" (2 :: Int) _ <- f "c" (3 :: Int) f `shouldBeCalled` inOrderWith ["a" ~> (1 :: Int), "b" ~> (2 :: Int), "c" ~> (3 :: Int)] it "shouldBeCalled inPartialOrderWith with IO mock" do f <- mock $ any ~> any ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "b" (2 :: Int) _ <- f "c" (3 :: Int) f `shouldBeCalled` inPartialOrderWith ["a" ~> (1 :: Int), "c" ~> (3 :: Int)] it "shouldBeCalled anything with IO mock" do f <- mock $ any ~> any ~> pure @IO True _ <- f "a" (1 :: Int) f `shouldBeCalled` anything it "shouldBeCalled times without args with IO mock" do f <- mock $ any ~> any ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "b" (2 :: Int) _ <- f "c" (3 :: Int) f `shouldBeCalled` times 3 describe "Named mocks (error messages)" do it "shouldBeCalled with name in error message" do f <- mock (label "named mock") $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) f `shouldBeCalled` ("b" ~> (1 :: Int)) `shouldThrow` anyErrorCall it "shouldBeCalled times with name in error message" do f <- mock (label "named mock") $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) let e = "function `named mock` was not called the expected number of times with the expected arguments.\n\ \ expected: 3\n\ \ but got: 2" f `shouldBeCalled` (times 3 `withArgs` ("a" ~> (1 :: Int))) `shouldThrow` errorCall e it "shouldBeCalled inOrderWith with name in error message" do f <- mock (label "named mock") $ any ~> any ~> pure @IO True _ <- f "b" (2 :: Int) _ <- f "a" (1 :: Int) _ <- f "c" (3 :: Int) f `shouldBeCalled` inOrderWith ["a" ~> (1 :: Int), "b" ~> (2 :: Int), "c" ~> (3 :: Int)] `shouldThrow` errorContains "expected 1st call:" it "shouldBeCalled inPartialOrderWith with name in error message" do f <- mock (label "named mock") $ any ~> any ~> pure @IO True _ <- f "b" (2 :: Int) _ <- f "a" (1 :: Int) let e = "function `named mock` was not called with the expected arguments in the expected order.\n\ \ expected order:\n\ \ \"a\",1\n\ \ \"c\",3\n\ \ but got:\n\ \ \"b\",2\n\ \ \"a\",1" f `shouldBeCalled` inPartialOrderWith ["a" ~> (1 :: Int), "c" ~> (3 :: Int)] `shouldThrow` errorCall e it "shouldBeCalled anything with name in error message" do f <- mock (label "named mock") $ "a" ~> (1 :: Int) ~> pure @IO True f `shouldBeCalled` anything `shouldThrow` errorCall "Function `named mock` was never called" describe "Non-Eq/Show support" do it "can verify calls with NoEq argument using anything" do f <- mock $ any @NoEq ~> "result" f (NoEq "val") `shouldBe` "result" f `shouldBeCalled` anything describe "Error messages" do it "shouldBeCalled failure with detailed error message" do f <- mock $ any ~> True evaluate $ f "A" -- The error message format uses showForMessage which may quote the value f `shouldBeCalled` "X" `shouldThrow` anyErrorCall it "shouldBeCalled times failure with detailed error message" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) let e = "function was not called the expected number of times with the expected arguments.\n\ \ expected: 3\n\ \ but got: 2" f `shouldBeCalled` (times 3 `withArgs` ("a" ~> (1 :: Int))) `shouldThrow` errorCall e it "shouldBeCalled with non-mock function shows guidance message" do let f :: Int -> Int f x = x (f `shouldBeCalled` times 1) `shouldThrow` errorCall verificationFailureMessage describe "Multiple arguments with typed values" do it "shouldBeCalled with multiple typed arguments" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) f `shouldBeCalled` ("a" ~> (1 :: Int)) it "shouldBeCalled times with multiple typed arguments" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) f `shouldBeCalled` (times 3 `withArgs` ("a" ~> (1 :: Int))) it "shouldBeCalled atLeast with multiple typed arguments" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) f `shouldBeCalled` (atLeast 3 `withArgs` ("a" ~> (1 :: Int))) it "shouldBeCalled atMost with multiple typed arguments" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) f `shouldBeCalled` (atMost 3 `withArgs` ("a" ~> (1 :: Int))) it "shouldBeCalled greaterThan with multiple typed arguments" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) f `shouldBeCalled` (greaterThan 2 `withArgs` ("a" ~> (1 :: Int))) it "shouldBeCalled lessThan with multiple typed arguments" do f <- mock $ "a" ~> (1 :: Int) ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) _ <- f "a" (1 :: Int) f `shouldBeCalled` (lessThan 4 `withArgs` ("a" ~> (1 :: Int))) it "shouldBeCalled inOrderWith with multiple typed arguments" do f <- mock $ any ~> any ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "b" (2 :: Int) _ <- f "c" (3 :: Int) f `shouldBeCalled` inOrderWith ["a" ~> (1 :: Int), "b" ~> (2 :: Int), "c" ~> (3 :: Int)] it "shouldBeCalled inPartialOrderWith with multiple typed arguments" do f <- mock $ any ~> any ~> pure @IO True _ <- f "a" (1 :: Int) _ <- f "b" (2 :: Int) _ <- f "c" (3 :: Int) f `shouldBeCalled` inPartialOrderWith ["a" ~> (1 :: Int), "c" ~> (3 :: Int)] describe "High arity mocks" do it "shouldBeCalled with arity 2" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" f `shouldBeCalled` ("a" ~> "b") it "shouldBeCalled with arity 3" do f <- mock $ "a" ~> "b" ~> "c" ~> False evaluate $ f "a" "b" "c" f `shouldBeCalled` ("a" ~> "b" ~> "c") it "shouldBeCalled times with arity 2" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (times 3 `withArgs` ("a" ~> "b")) it "shouldBeCalled times with arity 3" do f <- mock $ "a" ~> "b" ~> "c" ~> False evaluate $ f "a" "b" "c" evaluate $ f "a" "b" "c" f `shouldBeCalled` (times 2 `withArgs` ("a" ~> "b" ~> "c")) it "shouldBeCalled inOrderWith with arity 2" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" evaluate $ f "c" "d" f `shouldBeCalled` inOrderWith ["a" ~> "b", "c" ~> "d"] describe "Multi-case mocks" do it "shouldBeCalled with multiple cases (arity 1)" do f <- mock $ do onCase $ "1" ~> True onCase $ "2" ~> False evaluate $ f "1" evaluate $ f "2" f `shouldBeCalled` "1" f `shouldBeCalled` "2" it "shouldBeCalled with multiple cases (arity 2)" do f <- mock $ do onCase $ "1" ~> "2" ~> True onCase $ "2" ~> "3" ~> False evaluate $ f "1" "2" evaluate $ f "2" "3" f `shouldBeCalled` ("1" ~> "2") f `shouldBeCalled` ("2" ~> "3") it "shouldBeCalled times with multiple cases (arity 2)" do f <- mock $ do onCase $ "1" ~> "2" ~> True onCase $ "2" ~> "3" ~> False evaluate $ f "1" "2" evaluate $ f "1" "2" evaluate $ f "2" "3" evaluate $ f "2" "3" f `shouldBeCalled` (times 2 `withArgs` ("1" ~> "2")) f `shouldBeCalled` (times 2 `withArgs` ("2" ~> "3")) describe "Edge cases and boundary conditions" do it "times 0 (never called)" do f <- mock $ "a" ~> True f `shouldBeCalled` (times 0 `withArgs` "a") it "atLeast 0 (always succeeds)" do f <- mock $ "a" ~> True f `shouldBeCalled` (atLeast 0 `withArgs` "a") evaluate $ f "a" f `shouldBeCalled` (atLeast 0 `withArgs` "a") it "atLeast boundary (exact count)" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (atLeast 3 `withArgs` "a") it "atMost boundary (exact count)" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (atMost 3 `withArgs` "a") it "greaterThan boundary (one more)" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (greaterThan 2 `withArgs` "a") it "lessThan boundary (one less)" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (lessThan 3 `withArgs` "a") describe "Multiple arguments with Param combinators" do it "shouldBeCalled with multiple arguments using any" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" f `shouldBeCalled` (any ~> any) it "shouldBeCalled times with multiple arguments using any" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" evaluate $ f "c" "d" evaluate $ f "e" "f" f `shouldBeCalled` (times 3 `withArgs` (any ~> any)) it "shouldBeCalled with multiple arguments using expect" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" f `shouldBeCalled` (expect (const True) "always true" ~> expect (const True) "always true") it "shouldBeCalled times with multiple arguments using expect" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" evaluate $ f "c" "d" f `shouldBeCalled` (times 2 `withArgs` (expect (const True) "always true" ~> expect (const True) "always true")) it "shouldBeCalled anything with multiple arguments" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" f `shouldBeCalled` anything describe "High arity mocks (continued)" do it "shouldBeCalled with arity 9" do f <- mock $ any ~> any ~> any ~> any ~> any ~> any ~> any ~> any ~> () evaluate $ f "1" "2" "3" "4" "5" "6" "7" "8" f `shouldBeCalled` ("1" ~> "2" ~> "3" ~> "4" ~> "5" ~> "6" ~> "7" ~> "8") it "shouldBeCalled inOrderWith with arity 9" do f <- mock $ any ~> any ~> any ~> any ~> any ~> any ~> any ~> any ~> () evaluate $ f "1" "2" "3" "4" "5" "6" "7" "8" evaluate $ f "2" "3" "4" "5" "6" "7" "8" "9" evaluate $ f "3" "4" "5" "6" "7" "8" "9" "0" f `shouldBeCalled` inOrderWith [ "1" ~> "2" ~> "3" ~> "4" ~> "5" ~> "6" ~> "7" ~> "8", "2" ~> "3" ~> "4" ~> "5" ~> "6" ~> "7" ~> "8" ~> "9", "3" ~> "4" ~> "5" ~> "6" ~> "7" ~> "8" ~> "9" ~> "0" ] describe "Order verification edge cases" do it "inOrderWith with single element" do f <- mock $ any ~> () evaluate $ f "a" f `shouldBeCalled` inOrderWith ["a"] it "inPartialOrderWith with single element" do f <- mock $ any ~> () evaluate $ f "a" f `shouldBeCalled` inPartialOrderWith ["a"] it "inOrderWith with multiple arguments (failure case)" do f <- mock $ any ~> any ~> () evaluate $ f "a" "b" evaluate $ f "c" "d" f `shouldBeCalled` inOrderWith ["a" ~> "b", "d" ~> "c"] `shouldThrow` anyErrorCall it "inPartialOrderWith with multiple arguments (failure case)" do f <- mock $ any ~> any ~> () evaluate $ f "b" "a" evaluate $ f "c" "d" f `shouldBeCalled` inPartialOrderWith ["a" ~> "b", "c" ~> "d"] `shouldThrow` anyErrorCall describe "Count verification with multiple arguments" do it "once with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" f `shouldBeCalled` (once `withArgs` ("a" ~> "b")) it "once with multiple arguments (failure)" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (once `withArgs` ("a" ~> "b")) `shouldThrow` anyErrorCall it "never with multiple arguments" do f <- mock $ "a" ~> "b" ~> True f `shouldBeCalled` (never `withArgs` ("a" ~> "b")) it "never with multiple arguments (failure)" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" f `shouldBeCalled` (never `withArgs` ("a" ~> "b")) `shouldThrow` anyErrorCall it "atLeast with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (atLeast 2 `withArgs` ("a" ~> "b")) it "atMost with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (atMost 2 `withArgs` ("a" ~> "b")) it "greaterThan with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (greaterThan 1 `withArgs` ("a" ~> "b")) it "lessThan with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (lessThan 3 `withArgs` ("a" ~> "b")) describe "mockM" do it "records calls for monadic mocks" do f <- mockM $ "a" ~> True result <- f "a" result `shouldBe` True f `shouldBeCalled` "a" describe "Edge cases and boundary conditions" do it "times 0 (never called)" do f <- mock $ "a" ~> True f `shouldBeCalled` (times 0 `withArgs` "a") it "atLeast 0 (always succeeds)" do f <- mock $ "a" ~> True f `shouldBeCalled` (atLeast 0 `withArgs` "a") evaluate $ f "a" f `shouldBeCalled` (atLeast 0 `withArgs` "a") it "atLeast boundary (exact count)" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (atLeast 3 `withArgs` "a") it "atMost boundary (exact count)" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (atMost 3 `withArgs` "a") it "greaterThan boundary (one more)" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (greaterThan 2 `withArgs` "a") it "lessThan boundary (one less)" do f <- mock $ "a" ~> True evaluate $ f "a" evaluate $ f "a" f `shouldBeCalled` (lessThan 3 `withArgs` "a") describe "Multiple arguments with Param combinators" do it "shouldBeCalled with multiple arguments using any" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" f `shouldBeCalled` (any ~> any) it "shouldBeCalled times with multiple arguments using any" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" evaluate $ f "c" "d" evaluate $ f "e" "f" f `shouldBeCalled` (times 3 `withArgs` (any ~> any)) it "shouldBeCalled with multiple arguments using expect" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" f `shouldBeCalled` (expect (const True) "always true" ~> expect (const True) "always true") it "shouldBeCalled times with multiple arguments using expect" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" evaluate $ f "c" "d" f `shouldBeCalled` (times 2 `withArgs` (expect (const True) "always true" ~> expect (const True) "always true")) it "shouldBeCalled anything with multiple arguments" do f <- mock $ any ~> any ~> True evaluate $ f "a" "b" f `shouldBeCalled` anything describe "High arity mocks (continued)" do it "shouldBeCalled with arity 9" do f <- mock $ any ~> any ~> any ~> any ~> any ~> any ~> any ~> any ~> () evaluate $ f "1" "2" "3" "4" "5" "6" "7" "8" f `shouldBeCalled` inOrderWith ["1" ~> "2" ~> "3" ~> "4" ~> "5" ~> "6" ~> "7" ~> "8"] it "shouldBeCalled inOrderWith with arity 9" do f <- mock $ any ~> any ~> any ~> any ~> any ~> any ~> any ~> any ~> () evaluate $ f "1" "2" "3" "4" "5" "6" "7" "8" evaluate $ f "2" "3" "4" "5" "6" "7" "8" "9" evaluate $ f "3" "4" "5" "6" "7" "8" "9" "0" f `shouldBeCalled` inOrderWith [ "1" ~> "2" ~> "3" ~> "4" ~> "5" ~> "6" ~> "7" ~> "8", "2" ~> "3" ~> "4" ~> "5" ~> "6" ~> "7" ~> "8" ~> "9", "3" ~> "4" ~> "5" ~> "6" ~> "7" ~> "8" ~> "9" ~> "0" ] describe "Order verification edge cases" do it "inOrderWith with single element" do f <- mock $ any ~> () evaluate $ f "a" f `shouldBeCalled` inOrderWith ["a"] it "inPartialOrderWith with single element" do f <- mock $ any ~> () evaluate $ f "a" f `shouldBeCalled` inPartialOrderWith ["a"] it "inOrderWith with multiple arguments (failure case)" do f <- mock $ any ~> any ~> () evaluate $ f "a" "b" evaluate $ f "c" "d" f `shouldBeCalled` inOrderWith ["a" ~> "b", "d" ~> "c"] `shouldThrow` anyErrorCall it "inPartialOrderWith with multiple arguments (failure case)" do f <- mock $ any ~> any ~> () evaluate $ f "b" "a" evaluate $ f "c" "d" f `shouldBeCalled` inPartialOrderWith ["a" ~> "b", "c" ~> "d"] `shouldThrow` anyErrorCall describe "Count verification with multiple arguments" do it "once with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" f `shouldBeCalled` (once `withArgs` ("a" ~> "b")) it "once with multiple arguments (failure)" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (once `withArgs` ("a" ~> "b")) `shouldThrow` anyErrorCall it "never with multiple arguments" do f <- mock $ "a" ~> "b" ~> True f `shouldBeCalled` (never `withArgs` ("a" ~> "b")) it "never with multiple arguments (failure)" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" f `shouldBeCalled` (never `withArgs` ("a" ~> "b")) `shouldThrow` anyErrorCall it "atLeast with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (atLeast 2 `withArgs` ("a" ~> "b")) it "atMost with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (atMost 2 `withArgs` ("a" ~> "b")) it "greaterThan with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (greaterThan 1 `withArgs` ("a" ~> "b")) it "lessThan with multiple arguments" do f <- mock $ "a" ~> "b" ~> True evaluate $ f "a" "b" evaluate $ f "a" "b" f `shouldBeCalled` (lessThan 3 `withArgs` ("a" ~> "b")) errorContains :: String -> Selector ErrorCall errorContains sub (ErrorCall msg) = sub `isInfixOf` msg data NoEq = NoEq String deriving (Show)