Description
OCMockito is an Objective-C implementation of Mockito, supporting creation,
verification and stubbing of mock objects.
Key differences from other mocking frameworks:
OCMockito alternatives and similar libraries
Based on the "Other Testing" category.
Alternatively, view OCMockito alternatives based on common mentions on social networks and blogs.
-
PonyDebugger
Remote network and data debugging for your native iOS app using Chrome Developer Tools -
ios-snapshot-test-case
Snapshot view unit tests for iOS -
Mockingjay
An elegant library for stubbing HTTP requests with ease in Swift -
Buildasaur
Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running in minutes. @buildasaur -
NaughtyKeyboard
The Big List of Naughty Strings is a list of strings which have a high probability of causing issues when used as user-input data. This is a keyboard to help you test your app from your iOS device. -
trainer
Convert xcodebuild plist and xcresult files to JUnit reports -
Cribble
Swifty tool for visual testing iPhone and iPad apps. Every pixel counts. -
Mockingbird
Simplify software testing, by easily mocking any system using HTTP/HTTPS, allowing a team to test and develop against a service that is not complete or is unstable or just to reproduce planned/edge cases. -
Mockit
A simple mocking framework for Swift, inspired by the famous http://mockito.org/ -
AcceptanceMark
Tool for generating Acceptance Tests in Xcode, inspired by Fitnesse -
MetovaTestKit
A collection of useful test helpers designed to ease the burden of writing tests for iOS applications. -
SnappyTestCase
iOS Simulator type agnostic snapshot testing, built on top of the FBSnapshotTestCase. -
XCTestExtensions
XCTestExtensions is a Swift extension that provides convenient assertions for writing Unit Test. -
TestKit
The easiest way to implement full BDD in your Swift iOS projects! Use plain English specs (Gherkin) to drive tests that include both UI automation and interacting with application data & state. -
Bugfender Live
Stream the screen of an iOS device for live debugging. -
Parallel iOS Tests
Run iOS tests on multiple simulators in parallel at the same time
Appwrite - The open-source backend cloud platform
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of OCMockito or a related project?
README
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.
Let's verify some behavior!
// mock creation
NSMutableArray *mockArray = mock([NSMutableArray class]);
// using mock object
[mockArray addObject:@"one"];
[mockArray removeAllObjects];
// verification
[verify(mockArray) addObject:@"one"];
[verify(mockArray) removeAllObjects];
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?
// mock creation
NSArray *mockArray = mock([NSArray class]);
// stubbing
[given([mockArray objectAtIndex:0]) willReturn:@"first"];
[given([mockArray objectAtIndex:1]) willThrow:[NSException exceptionWithName:@"name"
reason:@"reason"
userInfo:nil]];
// following prints "first"
NSLog(@"%@", [mockArray objectAtIndex:0]);
// follows throws exception
NSLog(@"%@", [mockArray objectAtIndex:1]);
// following prints "(null)" because objectAtIndex:999 was not stubbed
NSLog(@"%@", [mockArray objectAtIndex:999]);
How do you mock a class object?
__strong Class mockStringClass = mockClass([NSString class]);
(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?
id <MyDelegate> delegate = mockProtocol(@protocol(MyDelegate));
Or, if you don't want it to contain any optional methods:
id <MyDelegate> delegate = mockProtocolWithoutOptionals(@protocol(MyDelegate));
How do you mock an object that also implements a protocol?
UIViewController <CustomProtocol> *controller =
mockObjectAndProtocol([UIViewController class], @protocol(CustomProtocol));
How do you stub methods that return primitives?
To stub methods that return primitive scalars, box the scalars into NSValues:
[given([mockArray count]) willReturn:@3];
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:
SomeStruct aStruct = {...};
[given([mockObject methodReturningStruct]) willReturnStruct:&aStruct
objCType:@encode(SomeStruct)];
How do you stub a property so that KVO works?
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":
stubProperty(mockEmployee, firstName, @"FIRST-NAME");
This stubs the firstName
property, valueForKey:
and valueForKeyPath:
.
Argument matchers
OCMockito verifies argument values by testing for equality. But when extra flexibility is required, you can specify OCHamcrest matchers.
// mock creation
NSMutableArray *mockArray = mock([NSMutableArray class]);
// using mock object
[mockArray removeObject:@"This is a test"];
// verification
[verify(mockArray) removeObject:startsWith(@"This is")];
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:
[[given([mockArray objectAtIndex:0]) withMatcher:anything() forArgument:0]
willReturn:@"foo"];
This is particularly useful for ignoring NSError **
parameters: pass in NULL
, but override it with an anything()
matcher.
Use the shortcut -withMatcher:
to specify a matcher for a single argument:
[[given([mockArray objectAtIndex:0]) withMatcher:anything()]
willReturn:@"foo"];
These methods are also available to specify matchers for verification. Just call
them after verify(…)
but before the invocation you want to verify:
[[verify(mockArray) withMatcher:greaterThan(@5])] removeObjectAtIndex:0];
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:
HCArgumentCaptor *argument = [[HCArgumentCaptor alloc] init];
[verify(mockObject) doSomething:(id)argument];
assertThat([argument.value nameAtIndex:0], is(@"Jon"));
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:
HCArgumentCaptor *argument = [[HCArgumentCaptor alloc] init];
[verify(mockArray) sortUsingComparator:(id)argument];
NSComparator block = argument.value;
assertThat(@(block(@"a", @"z")), is(@(NSOrderedAscending)));
Stubbing consecutive calls
[[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.
[given([mockObject someMethod:anything()]) willDo:^id (NSInvocation *invocation){
NSArray *args = [invocation mkt_arguments];
return @([args[0] intValue] * 2);
}];
// Following prints 4
NSLog(@"%@", [mockObject someMethod:@2]);
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.
__strong Class mockUserDefaultsClass = mockClass([NSUserDefaults class]);
NSUserDefaults* mockDefaults = mock([NSUserDefaults class]);
stubSingleton(mockUserDefaultsClass, standardUserDefaults);
[given([NSUserDefaults standardUserDefaults]) willReturn:mockDefaults];
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 using OCMockito either through CocoaPods or through the prebuilt frameworks, for iOS and macOS development.
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:
target 'MyTests' do
inherit! :search_paths
use_frameworks!
pod 'OCMockito', '~> 5.0'
end
Use the following imports:
@import OCHamcrest;
@import OCMockito;
Carthage
Add the following to your Cartfile:
github "jonreid/OCMockito" ~> 5.0
Then drag the the built frameworks (both OCHamcrest and OCMockito) from the appropriate Carthage/Build directory into your project, but with "Copy items into destination group's folder" disabled.
Prebuilt Frameworks
Prebuilt binaries are available on GitHub for OCMockito. You will also need OCHamcrest. The binaries are packaged as frameworks:
- OCMockitoIOS.framework for iOS development
- OCMockito.framework for macOS development
OCHamcrest comes in a similar scheme. Drag the appropriate frameworks for both
both OCMockito and OCHamcrest into your project, specifying "Copy items into
destination group's folder". Then specify -ObjC
in your "Other Linker Flags".
iOS Development:
Use the following imports:
@import OCHamcrestIOS;
@import OCMockitoIOS;
macOS Development:
Add a "Copy Files" build phase to copy OCMockito.framework and OCHamcrest.framework to your Products Directory.
Use the following imports:
@import OCHamcrest;
@import OCMockito;
Build Your Own
If you want to build OCMockito yourself, clone the repo, then
$ Frameworks/gethamcrest
$ cd Source
$ ./MakeDistribution.sh