OCMockito is an Objective-C implementation of Mockito, supporting creation,
verification and stubbing of mock objects.
Key differences from other mocking frameworks:
Mock objects are always “nice,” recording their calls instead of throwing
exceptions about unspecified invocations. This makes tests less fragile.
No expect-run-verify, making tests more readable. Mock objects record their
calls, then you verify the methods you want.
Verification failures are reported as unit test failures, identifying specific
lines instead of throwing exceptions. This makes it easier to identify
failures.
Use stubProperty(mock, property, stubbedValue). For example, say you have a
mock object named mockEmployee. It has a property firstName. You want to
stub it to return the value “FIRST-NAME”:
Verifying exact number of invocations / at least x / never
// using mock
[mockArray addObject:@"once"];
[mockArray addObject:@"twice"];
[mockArray addObject:@"twice"];
// the following two verifications work exactly the same
[verify(mockArray) addObject:@"once"];
[verifyCount(mockArray, times(1)) addObject:@"once"];
// verify exact number of invocations
[verifyCount(mockArray, times(2)) addObject:@"twice"];
[verifyCount(mockArray, times(3)) addObject:@"three times"];
// verify using never(), which is an alias for times(0)
[verifyCount(mockArray, never()) addObject:@"never happened"];
// verify using atLeast()/atMost()
[verifyCount(mockArray, atLeastOnce()) addObject:@"at least once"];
[verifyCount(mockArray, atLeast(2)) addObject:@"at least twice"];
[verifyCount(mockArray, atMost(5)) addObject:@"at most five times"];
Capturing arguments for further assertions
OCMockito verifies argument values using OCHamcrest matchers; non-matcher
arguments are implicitly wrapped in the equalTo matcher to test for equality.
In some situations though, it’s helpful to capture an argument so you can send
it another message.
OCHamcrest provides a special matcher for this purpose: HCArgumentCaptor.
Specify it as an argument, then query it with either the value or allValues
properties.
For example, you may want to send the captured argument a message to query its
state:
Capturing arguments is especially handy for block arguments. Capture the
argument, cast it to the block type, then invoke the block directly to simulate
the ways it will be called by production code:
[[given([mockObject someMethod:@"some arg"])
willThrow:[NSException exceptionWithName:@"name" reason:@"reason" userInfo:nil]]
willReturn:@"foo"];
// First call: throws exception
[mockObject someMethod:@"some arg"];
// Second call: prints "foo"
NSLog(@"%@", [mockObject someMethod:@"some arg"]);
// Any consecutive call: prints "foo" as well. (Last stubbing wins.)
NSLog(@"%@", [mockObject someMethod:@"some arg"]);
Stubbing with blocks
We recommend using simple stubbing with willReturn: or willThrow: only. But
willDo: using a block can sometimes be helpful. The block can easily access
invocation arguments by calling mkt_arguments from NSInvocation+OCMockito.h.
Whatever the block returns will be used as the stubbed return value.
You can stub a void method with a block by using givenVoid instead of given.
Problems with dealloc
Use stopMocking(…) if a -dealloc of your System Under Test is trying to
message an object that is mocked. It disables message handling on the mock and
frees its retained arguments. This prevents retain cycles and crashes during
test clean-up. See StopMockingTests.m for an example.
How do you mock a singleton?
The short answer is: Don’t. Instead of your class deciding who it’s going to
talk to, inject those dependencies.
The longer answer is: Well. Legacy code. Call stubSingleton on a mock class
object, specifying the name of the factory method.
Beware! This uses swizzling. You need to make sure the mock class object gets
deallocated so that the swizzling is undone.
In the example above, mockUserDefaultsClass will go out scope and be
destroyed. But what if you kept it in the test fixture, as an ivar or a
property? According to XCTest’s design, it won’t be implicitly destroyed.
You need to explicitly set it to nil in -tearDown, or the swizzling will
bleed over to your other tests, compromising their integrity.
If you need more control over when the swizzling is undone, call
stopMocking(…) on the mock class.
How do I add OCMockito to my project?
The Examples folder shows projects
ready to use OCMockito via Swift Package Manager, CocoaPods, or through the prebuilt framework.
Swift Package Manager
Include an OCMockito package in your Package.swift manifest’s array of dependencies:
If you want to add OCMockito using Cocoapods then add the following dependency
to your Podfile. Most people will want OCMockito in their test targets, and not
include any pods from their main targets:
target 'MyTests' do
inherit! :search_paths
use_frameworks!
pod 'OCMockito', '~> 7.0'
end
Carthage
Unfortunately, shifting the OCHamcrest dependency to an XCFramework has meant
dropping support for Carthage. Please let me know if this situation changes.
Prebuilt Framework
A prebuilt binary is available on GitHub for
OCMockito. You will also need
OCHamcrest.
The binary is packaged as OCMockito.xcframework, containing these architectures:
macOS
Mac Catalyst
iOS device
iOS simulator
tvOS device
tvOS simulator
watchOS device
watchOS simulator
Drag the XCFramework into your project.
Build Your Own
If you want to build OCMockito yourself, clone the repo, then
OCMockito
OCMockito is an Objective-C implementation of Mockito, supporting creation, verification and stubbing of mock objects.
Key differences from other mocking frameworks:
Mock objects are always “nice,” recording their calls instead of throwing exceptions about unspecified invocations. This makes tests less fragile.
No expect-run-verify, making tests more readable. Mock objects record their calls, then you verify the methods you want.
Verification failures are reported as unit test failures, identifying specific lines instead of throwing exceptions. This makes it easier to identify failures.
Contents
Let’s verify some behavior!
Once created, the mock will remember all interactions. Then you can selectively verify whatever interactions you are interested in.
(If Xcode complains about multiple methods with the same name, cast
verify
to the mocked class.)How about some stubbing?
How do you mock a class object?
(In the iOS 64-bit runtime, Class objects aren’t strong by default. Either make it explicitly strong as shown above, or use
id
instead.)How do you mock a protocol?
Or, if you don’t want it to contain any optional methods:
How do you mock an object that also implements a protocol?
How do you stub methods that return primitives?
To stub methods that return primitive scalars, box the scalars into NSValues:
How do you stub methods that return structs?
Use
willReturnStruct:objCType:
passing a pointer to your structure and its type from the Objective-C@encode()
compiler directive:How do you stub a property so that KVO works?
Use
stubProperty(mock, property, stubbedValue)
. For example, say you have a mock object namedmockEmployee
. It has a propertyfirstName
. You want to stub it to return the value “FIRST-NAME”:This stubs the
firstName
property,valueForKey:
andvalueForKeyPath:
.Argument matchers
OCMockito verifies argument values by testing for equality. But when extra flexibility is required, you can specify OCHamcrest matchers.
OCHamcrest matchers can be specified as arguments for both verification and stubbing.
Typed arguments will issue a warning that the matcher is the wrong type. Just cast the matcher to
id
.How do you specify matchers for non-object arguments?
To stub a method that takes a non-object argument but specify a matcher, invoke the method with a dummy argument, then call
-withMatcher:forArgument:
This is particularly useful for ignoring
NSError **
parameters: pass inNULL
, but override it with ananything()
matcher.Use the shortcut
-withMatcher:
to specify a matcher for a single argument:These methods are also available to specify matchers for verification. Just call them after
verify(…)
but before the invocation you want to verify:Verifying exact number of invocations / at least x / never
Capturing arguments for further assertions
OCMockito verifies argument values using OCHamcrest matchers; non-matcher arguments are implicitly wrapped in the
equalTo
matcher to test for equality. In some situations though, it’s helpful to capture an argument so you can send it another message.OCHamcrest provides a special matcher for this purpose: HCArgumentCaptor. Specify it as an argument, then query it with either the
value
orallValues
properties.For example, you may want to send the captured argument a message to query its state:
Capturing arguments is especially handy for block arguments. Capture the argument, cast it to the block type, then invoke the block directly to simulate the ways it will be called by production code:
Stubbing consecutive calls
Stubbing with blocks
We recommend using simple stubbing with
willReturn:
orwillThrow:
only. ButwillDo:
using a block can sometimes be helpful. The block can easily access invocation arguments by callingmkt_arguments
from NSInvocation+OCMockito.h. Whatever the block returns will be used as the stubbed return value.You can stub a void method with a block by using
givenVoid
instead ofgiven
.Problems with dealloc
Use
stopMocking(…)
if a-dealloc
of your System Under Test is trying to message an object that is mocked. It disables message handling on the mock and frees its retained arguments. This prevents retain cycles and crashes during test clean-up. See StopMockingTests.m for an example.How do you mock a singleton?
The short answer is: Don’t. Instead of your class deciding who it’s going to talk to, inject those dependencies.
The longer answer is: Well. Legacy code. Call
stubSingleton
on a mock class object, specifying the name of the factory method.Beware! This uses swizzling. You need to make sure the mock class object gets deallocated so that the swizzling is undone.
In the example above,
mockUserDefaultsClass
will go out scope and be destroyed. But what if you kept it in the test fixture, as an ivar or a property? According to XCTest’s design, it won’t be implicitly destroyed. You need to explicitly set it to nil in-tearDown
, or the swizzling will bleed over to your other tests, compromising their integrity.If you need more control over when the swizzling is undone, call
stopMocking(…)
on the mock class.How do I add OCMockito to my project?
The Examples folder shows projects ready to use OCMockito via Swift Package Manager, CocoaPods, or through the prebuilt framework.
Swift Package Manager
Include an OCMockito package in your Package.swift manifest’s array of
dependencies
:snippet source | anchor
Then add OCMockito to the dependencies of your
.testTarget
:snippet source | anchor
CocoaPods
If you want to add OCMockito using Cocoapods then add the following dependency to your Podfile. Most people will want OCMockito in their test targets, and not include any pods from their main targets:
Carthage
Unfortunately, shifting the OCHamcrest dependency to an XCFramework has meant dropping support for Carthage. Please let me know if this situation changes.
Prebuilt Framework
A prebuilt binary is available on GitHub for OCMockito. You will also need OCHamcrest. The binary is packaged as OCMockito.xcframework, containing these architectures:
Drag the XCFramework into your project.
Build Your Own
If you want to build OCMockito yourself, clone the repo, then