Rules

To work properly, mocks must comply with a few rules regarding return values, due to Swift strong typing.

Optional Return Value

The syntax is as follow:

func returnsOptional() -> Bool? {
return mock.call()
}

Here, call() returns nil or Void.

Non-Optional Return Value

For some methods, mocks must return non-optional values. If a return value type adopts the MockUsable protocol (which is the case for the most common types like Bool, Int…), just force unwrapping the result to call(), like in the following example:

How to Set Expectations?

Expectations aim at verifying that a call is done with some arguments. They are set using a syntax like in the following example:

// create mock instance
let mock = FooMock()
// create expectation on `mock`, that is verified when `bar` is called
// with "hello" for `arg1` and any value of the type of `arg2`
mock.expect().call(
mock.bar(arg1: Arg.eq("hello"), arg2: Arg.any())
)

Reject

Rejections are the contrary of expectations. They make sure no call is being done with some arguments. Simply use reject() instead of expect().

Number of calls

In addition, expectations and rejections can be set on the number of calls:
Use the following syntax:

// create expectation on `mock`, that is verified when 2 calls are done on `bar`
// with "hello" for `arg1` and any value of the type of `arg2`
mock.expect().call(
mock.bar(arg1: Arg.eq("hello"), arg2: Arg.any()),
count: 2
)

Properties

Setting expectations on properties can be done using the following syntax:

// create mock instance
let mock = FooPropertyMock()
// create expectation on `mock`, that is verified when the property `prop` is called
mock.expect().call(mock.prop)
// create expectation on `mock`, that is verified when the property `prop` is set
// with the exact value "hello"
mock.expect().call(
mock.property.set(mock.prop, value: Arg.eq("hello"))
)

Verifications

Verifying expectations and rejections is done this way:

// test fails when any of the expectations or rejections set on `mock` is not verified
mock.verify()

How to Stub Calls?

Stubs aim at performing actions when a function is called with some arguments. They are set using a syntax like in the following example:

// create mock instance
let mock = FooMock()
// create stubbed implementation of the `bar` method, which returns `true` when called
// with "hello" for `arg1` and any value of the type of `arg2`
mock.stub().call(
mock.bar(arg1: Arg.eq("hello"), arg2: Arg.any())
).andReturn(true)

Return Value

Set the return value with andReturn(…) on the stub instance.

Compute a Return Value

This is done with andReturn(closure: { _ in return … }) on the stub instance. This enables to return different values on the same stub, depending on some conditions.

Call Another Function

This is done with andDo( { _ in … } ) on the stub instance.

Throw an Error

This is done with andThrow(…) on the stub instance.

Chaining

Chaining several actions on the same stub is possible, given they don't confict. For example, it is possible to return a value and call another function, like in andReturn(true).andDo({ _ in print("something") }).

Rules:

the last closure registered by andDo is called first

the last error registered by andThrow is thrown

the last return value registered by andReturn is returned

otherwise, the last return value computation method, registered by andReturn(closure:), is called

Argument Matching

Expectations are verified only if arguments match what is registered. Same goes for calling stubbed implementations.

Exact Value

Matching an exact value is done with Arg.eq(…).

Any Value

Matching any value can be done for types that adopt the MockUsable protocol, with Arg.any().

Certain Condition

Matching a value that verifies a certain condition is done with Arg.verify({ _ in return … }).

Closure

Matching a closure is a special case. Use the following syntax: Arg.closure().

Limitation: closures can be matched as long as they have less than 5 arguments.

Argument Capturing

Arguments can also be captured for later use thanks to the ArgumentCaptor class.