Mocks
1 Basic Mock Construction
mock?
make-mock
mock-call
mock-calls
mock-called-with?
mock-num-calls
2 Rack  Unit Checks for Mocks
check-mock-called-with?
check-mock-num-calls
3 Mock Constructors
void-mock
const-mock
case-mock
4 Mocking Out Functions for Testing
define/  mock
define/  mock-as
6.3.90.900

Mocks

 (require mock) package: jack-mock

This library includes functions and forms for working with mocks. A mock is a "fake" function used in place of the real thing during testing to simplify the test and ensure only a single unit and not it’s complex dependencies is being tested. Mocks are most useful for testing code that calls side-effectful operations and IO.

source code: https://github.com/jackfirth/racket-mock

1 Basic Mock Construction

procedure

(mock? v)  boolean?

  v : any/c
Predicate identifying mocks.

Examples:
> (mock? (make-mock void))

#t

> (mock? void?)

#f

procedure

(make-mock proc)  mock?

  proc : procedure?
Returns a mocked version of proc. The mock may be used in place of proc anywhere and behaves just like proc. When used as a procedure, the returned mock? forwards the arguments it’s given to proc and records the argument list and the result proc returned in hidden mutable storage. This allows tests to verify that a mock was called with the right arguments.

Examples:
> (define displayln-mock (make-mock displayln))
> (displayln-mock "foo")

foo

> (mock? displayln-mock)

#t

> (define quotient/remainder-mock (make-mock quotient/remainder))
> (quotient/remainder-mock 10 3)

3

1

struct

(struct mock-call (args results)
    #:prefab)
  args : list?
  results : list?
A prefab structure containg the arguments and result values of a single call to a mock?.

procedure

(mock-calls mock)  (listof mock-call?)

  mock : mock?
Returns a list of all the mock-calls made so far with mock.

Examples:
> (define displayln-mock (make-mock displayln))
> (mock-calls displayln-mock)

'()

> (displayln-mock "foo")

foo

> (mock-calls displayln-mock)

'(#s(mock-call ("foo") (#<void>)))

> (define quotient/remainder-mock (make-mock quotient/remainder))
> (quotient/remainder-mock 10 3)

3

1

> (quotient/remainder-mock 3 2)

1

1

> (mock-calls quotient/remainder-mock)

'(#s(mock-call (3 2) (1 1)) #s(mock-call (10 3) (3 1)))

procedure

(mock-called-with? args mock)  boolean?

  args : list?
  mock : mock?
Returns #t if mock has ever been called with arguments that are equal? to args, returns #f otherwise.

In the list of arguments, supply by-position argument values first, in order. Then supply keyword arguments, in any order. Supply each keyword as a two-element list: (#:keyword value).

Examples:
> (define displayln-mock (make-mock displayln))
> (mock-called-with? '("foo") displayln-mock)

#f

> (displayln-mock "foo")

foo

> (mock-called-with? '("foo") displayln-mock)

#t

> (require racket/format)
> (define ~a-mock (make-mock ~a))
> (~a-mock 0 #:width 3 #:align 'left)

"0  "

> (mock-called-with? '(0 [#:align left] [#:width 3]) ~a-mock)

#t

> (mock-called-with? '(0 [#:width 3] [#:align left]) ~a-mock)

#t

procedure

(mock-num-calls mock)  exact-nonnegative-integer?

  mock : mock?
Returns the number of times mock has been called.

Examples:
> (define displayln-mock (make-mock displayln))
> (mock-num-calls displayln-mock)

0

> (displayln-mock "foo")

foo

> (mock-num-calls displayln-mock)

1

2 RackUnit Checks for Mocks

procedure

(check-mock-called-with? args mock)  void?

  args : list?
  mock : mock?
A rackunit check that fails if mock has never been called with args.

Example:
> (check-mock-called-with? '(some args) (void-mock))

--------------------

FAILURE

name:       check-mock-called-with?

location:   (#<path:/home/racket/build-pkgs/user/.racket/6.3.90.900/pkgs/jack-mock/mock/private/check.rkt> 10 4 138 23)

expression: (check-mock-called-with? args2 mock3)

params:     ((some args) #<procedure:...t/private/kw.rkt:213:14>)

Check failure

--------------------

procedure

(check-mock-num-calls n mock)  void?

  n : exact-positive-integer?
  mock : mock?
A rackunit check that fails if mock hasn’t been called exactly n times.

Example:
> (check-mock-num-calls 1 (void-mock))

--------------------

FAILURE

name:       check-mock-num-calls

location:   (#<path:/home/racket/build-pkgs/user/.racket/6.3.90.900/pkgs/jack-mock/mock/private/check.rkt> 11 4 189 20)

expression: (check-mock-num-calls expected-num-calls15 mock16)

params:     (1 #<procedure:...t/private/kw.rkt:213:14>)

Check failure

--------------------

3 Mock Constructors

procedure

(void-mock)  mock?

Constructs a mock that acts like void. Useful for mocking procedures called only for their side effects like display.

Examples:
> (define a-void-mock (void-mock))
> (a-void-mock)
> (a-void-mock 1 2 3)
> (mock-num-calls a-void-mock)

2

procedure

(const-mock v)  mock?

  v : any/c
Constructs a mock that acts like (const v). Useful for making an IO reading operation return a test-defined value without actually doing any IO.

Examples:
> (define foo-mock (const-mock 'foo))
> (foo-mock 'bar)

'foo

procedure

(case-mock case-v case-result ... ...)  mock?

  case-v : any/c
  case-result : any/c
Constructs a mock that accepts a single value and compares it to each case-v with equal?, then returns the corresponding case-result for the first case-v that is equal? to the given value. If no case-v matches, an exception is thrown.

Examples:
> (define foo-bar-mock (case-mock 'foo 1 'bar 2))
> (foo-bar-mock 'foo)

1

> (foo-bar-mock 'bar)

2

> (foo-bar-mock 'unexpected)

v: contract violation

  expected: (or/c)

  given: 'unexpected

4 Mocking Out Functions for Testing

Mocks by themselves provide useful low-level building blocks, but often to use them a function needs to be implemented twice - once using mocks for the purpose of testing, and once using real functions to provide actual functionality. These syntactic forms provide shorthands for defining both implementations at once.

syntax

(define/mock header ([mock-id mock-expr] ...) body ...)

 
header = id
  | (header arg ...)
 
  mock-expr : mock?
Like define, but also defines a mocked version of id in a test submodule. The mocked version uses the same body ... as the unmocked version, but each mock-id is shadowed and bound to mock-expr in the test submodule and used in place of mock-id in body .... Each mock-id is left alone in the normal implementation.

Examples:
> (module m racket
    (require mock)
    (define/mock (displayln-twice v)
      ([displayln (void-mock)])
      (displayln v)
      (displayln v))
    (displayln-twice "sent to real displayln")
    (mock? displayln)
    (module+ test
      (displayln-twice "sent to mock displayln")
      (mock? displayln)))
> (require 'm)

sent to real displayln

sent to real displayln

#f

> (require (submod 'm test))

sent to mock displayln

sent to mock displayln

#f

syntax

(define/mock-as header (mock-clause ...) body ...)

 
header = id
  | (header arg ...)
     
mock-clause = [mock-id mock-value-id mock-expr]
 
  mock-expr : mock?
Like define/mock, but in the test submodule each mock-expr is bound as mock-value-id instead. This prevents shadowing in the submodule so that both the mocked and unmocked versions are available, and allows the mock value to be named something other than mock-id.

Examples:
> (module m racket
    (require mock)
    (define/mock-as (displayln-twice v)
      ([displayln displayln-mock (void-mock)])
      (displayln v)
      (displayln v))
    (displayln-twice "sent to real displayln")
    (mock? displayln)
    (module+ test
      (displayln-twice "sent to mock displayln")
      (mock? displayln)
      (mock? displayln-mock)))

eval:2:0: displayln-mock: unbound identifier in module

  context...:

   #(170972 module) #(170973 module m 0) #(172413 module)

   #(172414 module (m test) 0) #(172450 local) #(172451

intdef)

  other binding...:

   #<module-path-index:()>

   #(170972 module) #(170973 module m 0) #(171008 macro)

#(172413 module)

   #(172414 module (m test) 0)

  in: displayln-mock

> (require 'm)

require: unknown module

  module name: #<resolved-module-path:'m>

> (require (submod 'm test))

require: unknown module

  module name: #<resolved-module-path:(submod 'm test)>