{"id":15160677,"url":"https://github.com/jonreid/ocmockito","last_synced_at":"2025-05-14T06:14:04.962Z","repository":{"id":1920050,"uuid":"2847947","full_name":"jonreid/OCMockito","owner":"jonreid","description":"Mockito for Objective-C: creation, verification and stubbing of mock objects","archived":false,"fork":false,"pushed_at":"2025-03-02T06:19:42.000Z","size":5648,"stargazers_count":991,"open_issues_count":8,"forks_count":121,"subscribers_count":23,"default_branch":"main","last_synced_at":"2025-05-11T02:01:49.990Z","etag":null,"topics":["mocking","mocking-framework","mockito","objective-c","testing","xctest"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonreid.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2011-11-25T06:07:25.000Z","updated_at":"2025-04-10T22:04:13.000Z","dependencies_parsed_at":"2024-01-08T02:03:20.706Z","dependency_job_id":"30710b0b-ef17-4299-b7c4-63a3eed83f2e","html_url":"https://github.com/jonreid/OCMockito","commit_stats":{"total_commits":1100,"total_committers":37,"mean_commits":29.72972972972973,"dds":0.5318181818181817,"last_synced_commit":"2729960c35aa80c4accf680b155ca11d94e0c61c"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonreid%2FOCMockito","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonreid%2FOCMockito/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonreid%2FOCMockito/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonreid%2FOCMockito/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonreid","download_url":"https://codeload.github.com/jonreid/OCMockito/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254083809,"owners_count":22011902,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mocking","mocking-framework","mockito","objective-c","testing","xctest"],"created_at":"2024-09-26T23:05:17.007Z","updated_at":"2025-05-14T06:14:04.937Z","avatar_url":"https://github.com/jonreid.png","language":"Objective-C","readme":"![mockito](https://raw.githubusercontent.com/mockito/mockito.github.io/master/img/logo.png)\n\n# OCMockito\n\n[![Build Status](https://github.com/jonreid/OCMockito/actions/workflows/build.yml/badge.svg)](https://github.com/jonreid/OCMockito/actions/workflows/build.yml)\n[![Coverage Status](https://coveralls.io/repos/jonreid/OCMockito/badge.svg)](https://coveralls.io/r/jonreid/OCMockito)\n[![Swift Package Index Platform Compatibility](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fjonreid%2FOCMockito%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/jonreid/OCMockito)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![CocoaPods Version](https://img.shields.io/cocoapods/v/OCMockito.svg?style=flat)](https://cocoapods.org/pods/OCMockito)\n[![Mastodon Follow](https://img.shields.io/mastodon/follow/109765011064804734?domain=https%3A%2F%2Fiosdev.space\n)](https://iosdev.space/@qcoding)\n\nOCMockito is an Objective-C implementation of Mockito, supporting creation,\nverification and stubbing of mock objects.\n\nKey differences from other mocking frameworks:\n\n* Mock objects are always \"nice,\" recording their calls instead of throwing\n  exceptions about unspecified invocations. This makes tests less fragile.\n\n* No expect-run-verify, making tests more readable. Mock objects record their\n  calls, then you verify the methods you want.\n\n* Verification failures are reported as unit test failures, identifying specific\n  lines instead of throwing exceptions. This makes it easier to identify\n  failures.\n\n\u003c!-- toc --\u003e\n## Contents\n\n  * [Let's verify some behavior!](#lets-verify-some-behavior)\n  * [How about some stubbing?](#how-about-some-stubbing)\n  * [How do you mock a class object?](#how-do-you-mock-a-class-object)\n  * [How do you mock a protocol?](#how-do-you-mock-a-protocol)\n  * [How do you mock an object that also implements a protocol?](#how-do-you-mock-an-object-that-also-implements-a-protocol)\n  * [How do you stub methods that return primitives?](#how-do-you-stub-methods-that-return-primitives)\n  * [How do you stub methods that return structs?](#how-do-you-stub-methods-that-return-structs)\n  * [How do you stub a property so that KVO works?](#how-do-you-stub-a-property-so-that-kvo-works)\n  * [Argument matchers](#argument-matchers)\n  * [How do you specify matchers for non-object arguments?](#how-do-you-specify-matchers-for-non-object-arguments)\n  * [Verifying exact number of invocations / at least x / never](#verifying-exact-number-of-invocations--at-least-x--never)\n  * [Capturing arguments for further assertions](#capturing-arguments-for-further-assertions)\n  * [Stubbing consecutive calls](#stubbing-consecutive-calls)\n  * [Stubbing with blocks](#stubbing-with-blocks)\n  * [Problems with dealloc](#problems-with-dealloc)\n  * [How do you mock a singleton?](#how-do-you-mock-a-singleton)\n  * [How do I add OCMockito to my project?](#how-do-i-add-ocmockito-to-my-project)\n    * [Swift Package Manager](#swift-package-manager)\n    * [CocoaPods](#cocoapods)\n    * [Carthage](#carthage)\n    * [Prebuilt Framework](#prebuilt-framework)\n    * [Build Your Own](#build-your-own)\n  * [Author](#author)\u003c!-- endToc --\u003e\n\n## Let's verify some behavior!\n\n```obj-c\n// mock creation\nNSMutableArray *mockArray = mock([NSMutableArray class]);\n\n// using mock object\n[mockArray addObject:@\"one\"];\n[mockArray removeAllObjects];\n\n// verification\n[verify(mockArray) addObject:@\"one\"];\n[verify(mockArray) removeAllObjects];\n```\n\nOnce created, the mock will remember all interactions. Then you can selectively\nverify whatever interactions you are interested in.\n\n(If Xcode complains about multiple methods with the same name, cast `verify`\nto the mocked class.)\n\n\n## How about some stubbing?\n\n```obj-c\n// mock creation\nNSArray *mockArray = mock([NSArray class]);\n\n// stubbing\n[given([mockArray objectAtIndex:0]) willReturn:@\"first\"];\n[given([mockArray objectAtIndex:1]) willThrow:[NSException exceptionWithName:@\"name\"\n                                                                      reason:@\"reason\"\n                                                                    userInfo:nil]];\n\n// following prints \"first\"\nNSLog(@\"%@\", [mockArray objectAtIndex:0]);\n\n// follows throws exception\nNSLog(@\"%@\", [mockArray objectAtIndex:1]);\n\n// following prints \"(null)\" because objectAtIndex:999 was not stubbed\nNSLog(@\"%@\", [mockArray objectAtIndex:999]);\n```\n\n\n## How do you mock a class object?\n\n```obj-c\n__strong Class mockStringClass = mockClass([NSString class]);\n```\n\n(In the iOS 64-bit runtime, Class objects aren't strong by default. Either make\nit explicitly strong as shown above, or use `id` instead.)\n\n\n## How do you mock a protocol?\n\n```obj-c\nid \u003cMyDelegate\u003e delegate = mockProtocol(@protocol(MyDelegate));\n```\n\nOr, if you don't want it to contain any optional methods:\n\n```obj-c\nid \u003cMyDelegate\u003e delegate = mockProtocolWithoutOptionals(@protocol(MyDelegate));\n```\n\n\n## How do you mock an object that also implements a protocol?\n\n```obj-c\nUIViewController \u003cCustomProtocol\u003e *controller =\n    mockObjectAndProtocol([UIViewController class], @protocol(CustomProtocol));\n```\n\n\n## How do you stub methods that return primitives?\n\nTo stub methods that return primitive scalars, box the scalars into NSValues:\n\n```obj-c\n[given([mockArray count]) willReturn:@3];\n```\n\n\n## How do you stub methods that return structs?\n\nUse `willReturnStruct:objCType:` passing a pointer to your structure and its\ntype from the Objective-C `@encode()` compiler directive:\n\n```obj-c\nSomeStruct aStruct = {...};\n[given([mockObject methodReturningStruct]) willReturnStruct:\u0026aStruct\n                                                   objCType:@encode(SomeStruct)];\n```\n\n\n## How do you stub a property so that KVO works?\n\nUse `stubProperty(mock, property, stubbedValue)`. For example, say you have a\nmock object named `mockEmployee`. It has a property `firstName`. You want to\nstub it to return the value \"FIRST-NAME\":\n\n```obj-c\nstubProperty(mockEmployee, firstName, @\"FIRST-NAME\");\n```\n\nThis stubs the `firstName` property, `valueForKey:` and `valueForKeyPath:`.\n\n\n## Argument matchers\n\nOCMockito verifies argument values by testing for equality. But when extra\nflexibility is required, you can specify\n [OCHamcrest](https://github.com/hamcrest/OCHamcrest) matchers.\n\n```obj-c\n// mock creation\nNSMutableArray *mockArray = mock([NSMutableArray class]);\n\n// using mock object\n[mockArray removeObject:@\"This is a test\"];\n\n// verification\n[verify(mockArray) removeObject:startsWith(@\"This is\")];\n```\n\nOCHamcrest matchers can be specified as arguments for both verification and\nstubbing.\n\nTyped arguments will issue a warning that the matcher is the wrong type. Just\ncast the matcher to `id`.\n\n\n## How do you specify matchers for non-object arguments?\n\nTo stub a method that takes a non-object argument but specify a matcher, invoke\nthe method with a dummy argument, then call `-withMatcher:forArgument:`\n\n```obj-c\n[[given([mockArray objectAtIndex:0]) withMatcher:anything() forArgument:0]\n willReturn:@\"foo\"];\n```\n\nThis is particularly useful for ignoring `NSError **` parameters: pass in `NULL`, but override it with an `anything()` matcher.\n\nUse the shortcut `-withMatcher:` to specify a matcher for a single argument:\n\n```obj-c\n[[given([mockArray objectAtIndex:0]) withMatcher:anything()]\n willReturn:@\"foo\"];\n```\n\nThese methods are also available to specify matchers for verification. Just call\nthem after `verify(…)` but before the invocation you want to verify:\n\n```obj-c\n[[verify(mockArray) withMatcher:greaterThan(@5])] removeObjectAtIndex:0];\n```\n\n\n## Verifying exact number of invocations / at least x / never\n\n```obj-c\n// using mock\n[mockArray addObject:@\"once\"];\n\n[mockArray addObject:@\"twice\"];\n[mockArray addObject:@\"twice\"];\n\n// the following two verifications work exactly the same\n[verify(mockArray) addObject:@\"once\"];\n[verifyCount(mockArray, times(1)) addObject:@\"once\"];\n\n// verify exact number of invocations\n[verifyCount(mockArray, times(2)) addObject:@\"twice\"];\n[verifyCount(mockArray, times(3)) addObject:@\"three times\"];\n\n// verify using never(), which is an alias for times(0)\n[verifyCount(mockArray, never()) addObject:@\"never happened\"];\n\n// verify using atLeast()/atMost()\n[verifyCount(mockArray, atLeastOnce()) addObject:@\"at least once\"];\n[verifyCount(mockArray, atLeast(2)) addObject:@\"at least twice\"];\n[verifyCount(mockArray, atMost(5)) addObject:@\"at most five times\"];\n```\n\n\n## Capturing arguments for further assertions\n\nOCMockito verifies argument values using OCHamcrest matchers; non-matcher\narguments are implicitly wrapped in the `equalTo` matcher to test for equality.\nIn some situations though, it's helpful to capture an argument so you can send\nit another message.\n\nOCHamcrest provides a special matcher for this purpose: HCArgumentCaptor.\nSpecify it as an argument, then query it with either the `value` or `allValues`\nproperties.\n\nFor example, you may want to send the captured argument a message to query its\nstate:\n\n```obj-c\nHCArgumentCaptor *argument = [[HCArgumentCaptor alloc] init];\n[verify(mockObject) doSomething:(id)argument];\nassertThat([argument.value nameAtIndex:0], is(@\"Jon\"));\n```\n\nCapturing arguments is especially handy for block arguments. Capture the\nargument, cast it to the block type, then invoke the block directly to simulate\nthe ways it will be called by production code:\n\n```obj-c\nHCArgumentCaptor *argument = [[HCArgumentCaptor alloc] init];\n[verify(mockArray) sortUsingComparator:(id)argument];\nNSComparator block = argument.value;\nassertThat(@(block(@\"a\", @\"z\")), is(@(NSOrderedAscending)));\n```\n\n\n## Stubbing consecutive calls\n\n```obj-c\n[[given([mockObject someMethod:@\"some arg\"])\n    willThrow:[NSException exceptionWithName:@\"name\" reason:@\"reason\" userInfo:nil]]\n    willReturn:@\"foo\"];\n\n// First call: throws exception\n[mockObject someMethod:@\"some arg\"];\n\n// Second call: prints \"foo\"\nNSLog(@\"%@\", [mockObject someMethod:@\"some arg\"]);\n\n// Any consecutive call: prints \"foo\" as well. (Last stubbing wins.)\nNSLog(@\"%@\", [mockObject someMethod:@\"some arg\"]);\n```\n\n\n## Stubbing with blocks\n\nWe recommend using simple stubbing with `willReturn:` or `willThrow:` only. But\n`willDo:` using a block can sometimes be helpful. The block can easily access\ninvocation arguments by calling `mkt_arguments` from NSInvocation+OCMockito.h.\nWhatever the block returns will be used as the stubbed return value.\n\n```obj-c\n[given([mockObject someMethod:anything()]) willDo:^id (NSInvocation *invocation){\n    NSArray *args = [invocation mkt_arguments];\n    return @([args[0] intValue] * 2);\n}];\n\n// Following prints 4\nNSLog(@\"%@\", [mockObject someMethod:@2]);\n```\n\nYou can stub a void method with a block by using `givenVoid` instead of `given`.\n\n\n## Problems with dealloc\n\nUse `stopMocking(…)` if a `-dealloc` of your System Under Test is trying to\nmessage an object that is mocked. It disables message handling on the mock and\nfrees its retained arguments. This prevents retain cycles and crashes during\ntest clean-up. See StopMockingTests.m for an example.\n\n\n## How do you mock a singleton?\n\nThe short answer is: Don't. Instead of your class deciding who it's going to\ntalk to, inject those dependencies.\n\nThe longer answer is: Well. Legacy code. Call `stubSingleton` on a mock class\nobject, specifying the name of the factory method.\n\n```obj-c\n__strong Class mockUserDefaultsClass = mockClass([NSUserDefaults class]);\nNSUserDefaults* mockDefaults = mock([NSUserDefaults class]);\n\nstubSingleton(mockUserDefaultsClass, standardUserDefaults);\n[given([NSUserDefaults standardUserDefaults]) willReturn:mockDefaults];\n```\n\nBeware! This uses swizzling. You need to make sure the mock class object gets\ndeallocated so that the swizzling is undone.\n\nIn the example above, `mockUserDefaultsClass` will go out scope and be\ndestroyed. But what if you kept it in the test fixture, as an ivar or a\nproperty? According to XCTest's design, it won't be implicitly destroyed.\nYou need to explicitly set it to nil in `-tearDown`, or the swizzling will\nbleed over to your other tests, compromising their integrity.\n\nIf you need more control over when the swizzling is undone, call\n`stopMocking(…)` on the mock class.\n\n\n## How do I add OCMockito to my project?\n\nThe [Examples](https://github.com/jonreid/OCMockito/tree/main/Examples) folder shows projects\nready to use OCMockito via Swift Package Manager, CocoaPods, or through the prebuilt framework.\n\n### Swift Package Manager\n\nInclude an OCMockito package in your Package.swift manifest's array of `dependencies`:\n\n\u003c!-- snippet: swiftpm-declare-dependencies --\u003e\n\u003ca id='snippet-swiftpm-declare-dependencies'\u003e\u003c/a\u003e\n```swift\ndependencies: [\n    .package(\n        url: \"https://github.com/jonreid/OCMockito\",\n        .upToNextMajor(from: \"7.0.0\")\n    ),\n],\n```\n\u003csup\u003e\u003ca href='/Examples/MacExample-SwiftPackageManager/Package.swift#L13-L20' title='Snippet source file'\u003esnippet source\u003c/a\u003e | \u003ca href='#snippet-swiftpm-declare-dependencies' title='Start of snippet'\u003eanchor\u003c/a\u003e\u003c/sup\u003e\n\u003c!-- endSnippet --\u003e\n\nThen add OCMockito to the dependencies of your `.testTarget`:\n\n\u003c!-- snippet: swiftpm-use-dependencies --\u003e\n\u003ca id='snippet-swiftpm-use-dependencies'\u003e\u003c/a\u003e\n```swift\n.testTarget(\n    name: \"ExampleTests\",\n    dependencies: [\n        \"Example\",\n        \"OCMockito\",\n    ]\n),\n```\n\u003csup\u003e\u003ca href='/Examples/MacExample-SwiftPackageManager/Package.swift#L27-L35' title='Snippet source file'\u003esnippet source\u003c/a\u003e | \u003ca href='#snippet-swiftpm-use-dependencies' title='Start of snippet'\u003eanchor\u003c/a\u003e\u003c/sup\u003e\n\u003c!-- endSnippet --\u003e\n\n### CocoaPods\n\nIf you want to add OCMockito using Cocoapods then add the following dependency\nto your Podfile. Most people will want OCMockito in their test targets, and not\ninclude any pods from their main targets:\n\n```ruby\ntarget 'MyTests' do\n  inherit! :search_paths\n  use_frameworks!\n  pod 'OCMockito', '~\u003e 7.0'\nend\n```\n\n### Carthage\n\nAdd the following to your Cartfile:\n\n```\ngithub \"jonreid/OCMockito\" ~\u003e 7.0\n```\n\nThen drag the the built frameworks (both OCHamcrest and OCMockito) from the\nappropriate Carthage/Build directory into your project, but with \"Copy items\ninto destination group's folder\" disabled.\n\n### Prebuilt Framework\n\nA prebuilt binary is available on GitHub for\n[OCMockito](https://github.com/jonreid/OCMockito/releases/). You will also need\n[OCHamcrest](https://github.com/hamcrest/OCHamcrest/releases/).\nThe binary is packaged as OCMockito.xcframework, containing these architectures:\n* macOS\n* Mac Catalyst\n* iOS device\n* iOS simulator\n* tvOS device\n* tvOS simulator\n* visionOS device\n* visionOS simulator\n* watchOS device\n* watchOS simulator\n\nDrag the XCFramework into your project.\n\n### Build Your Own\n\nIf you want to build OCMockito yourself, clone the repo, then\n\n```sh\n$ cd Source\n$ ./MakeDistribution.sh\n```\n\n## Author\n\nJon Reid is the author of _[iOS Unit Testing by Example](https://iosunittestingbyexample.com)._ His website is [Quality Coding](https://qualitycoding.org).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonreid%2Focmockito","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonreid%2Focmockito","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonreid%2Focmockito/lists"}