|
|
|
|
OCMock is an Objective-C implementation of mock objects. If you are unfamiliar with the concept of mock objects please visit mockobjects.com which has more details and discussions about this approach to testing software. This implementation fully utilises the dynamic nature of Objective-C. It creates mock objects on the fly and uses the trampoline pattern so that you can define expectations and stubs using the same syntax that you use to call methods. No strings, no @selector, just method invocations like this: [[myMockObject expect] doSomethingWithObject:someObject];
Pre-built binaries as well as instructions on how to access the source code are available on the "Download" tab. The "Features" tab lists all features supported by OCMock. Support details, including a link to the support forum, are on the "Support" tab. 20-Aug-2011Some infrastructure changes. Following public demand the source code for OCMock is now on GitHub (erikdoe/ocmock). Going forward this will be the master repository for the source code. Because the current version numbers are based on the Subversion revisions we will introduce a new numbering scheme with the next release. At the same time the website is moving to its own top-level domain, ocmock.org. 17-Mar-2011New release (1.77) bringing Xcode 4 compatibility, an explicit check to see whether the static library has been linked correctly, and a feature to stop a partial mock from intercepting calls to the underlying object. 21-Aug-2010New release (1.70) which adds the following features: support for blocks, static library for iOS development, forwarding of methods from a partial mock to the real object, and rejecting methods when using nice mocks. All new features are highlighted on the "Features" tab on this page, and the static library is described in detail on the "iPhone/iOS" tab. 16-Oct-2009New release (1.55) offering several new features, including partial mocks, method swizzling, posting of notifications, and verification of call sequence, as well as a handful of bug fixes. Details in the "Features" tab on this page and in the change notes. 10-Oct-2009The mailing list is great for submitting patches and discussing future development of OCMock. To just get a quick answer for a problem using OCMock it might be a bit too involved, which is why we're going to trial the use of a web-based forum. Have a look at the brand new OCMock Forum. 19-May-2009New release (1.42) which combines several contributions, adding support for mock observers of notifications, setters for pass-by-reference arguments, and several improvements to existing features. The default binary release now uses @rpath, which allows for more flexible deployment, and it supports garbage collection. 07-Jul-2008With this new release (1.29) OCMock supports hamcrest matchers like this: [[mock expect] doSomething:startsWith(@"foo")]
Note that this dependency is optional. OCMock does not require or link against hamcrest, but if the test suite uses hamcrest matchers and links against hamcrest then OCMock works with the matchers. This release also contains a small bugfix that removes a memory leak in OCMockRecorder. 08-May-2008New release (1.24) which combines several contributions, adds support for more flexible constraints as well as experimental 64-bit support. The default binary release is now in “embedded” mode. 22-Nov-2007We now have a mailing list for OCMock. Please send an empty message to ocmock-subscribe@mulle-kybernetik.com to subscribe. The actual mailing list address is ocmock@mulle-kybernetik.com but you must be subscribed to be able to post. (Too much hassle with spam otherwise.) 21-Jun-2007New release (1.17) which combines several contributions. Added nice mocks, which ignore unexpected invocations, and exceptions meant to cause the test to fail fast are now rethrown in verify. 11-Jun-2006New release (1.12) which combines several contributions. Added support for stubbing primitive return types, matching nil and struct arguments, and throwing exceptions. 03-Oct-2005New release (1.10) which has support for mocking protocols. Also added XCode 2.1 compliant project files and moved to built-in OCUnit. 26-Sep-2004Changed a small but important detail: The MockObject and MockRecorder classes now inherit from NSProxy which carries much less baggage in terms of methods that cannot be mocked because they are defined by the base class. 30-Aug-2004First public release. I am using the Subversion revision numbers to version the releases, which is why we start with 1.4 and not 1.0 as one could expect. 23-Jul-2004While working on a new Objective-C project, a Mac OS X monitor for Damage Control, I decide that I've gotten so used to developing test-first and using mock objects that I will bite the bullet and do a simple mock objects implementation in Objective-C. It'll be basic but since Objective-C is so dynamic I probably only need a fraction of the code needed for the Java and .NET versions. Stable ReleasesThe binaries require the lowest version of OS X and the iOS SDK that supports all features. It is usually possible to build a given version of OCMock from source for older versions of OS X at the expense of losing some features.
Source codeThe source code for OCMock is available on GitHub
https://github.com/erikdoe/ocmock
LicenseCopyright (c) 2004 - 2012 by Mulle Kybernetik. All rights reserved. Permission to use, copy, modify and distribute this software and its documentation is hereby granted, provided that both the copyright notice and this permission notice appear in all copies of the software, derivative works or modified versions, and any portions thereof, and that both notices appear in supporting documentation, and that credit is given to Mulle Kybernetik in all documents and publicity pertaining to direct or indirect use of this code or its derivatives. THIS IS EXPERIMENTAL SOFTWARE AND IT IS KNOWN TO HAVE BUGS, SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. THE COPYRIGHT HOLDER ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. THE COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF ANY DERIVATIVE WORK. Class mocks
Creates a mock object that can be used as if it were an instance of SomeClass. Expectations and verification
Tells the mock object that someMethod: should be called with an argument that is equal to someArgument. After this setup the functionality under test should be invoked followed by
The verify method will raise an exception if the expected method has not been invoked. Stubs
Tells the mock object that when someMethod: is called with someArgument it should return aValue. If the method returns a primitive type the return value must be wrapped as follows:
Values can also be returned in pass-by-reference arguments:
In this case the mock object will set the reference that is passed to the method to aValue, which currently has to be an object. The mock object can also throw an exception or post a notification when a method is called:
In fact, the notification can be posted in addition to returning a value:
The mock can delegate the handling of an invocation to a completely different method:
In this case the mock object will call aMethod: on anObject when someMethod: is called. The signature of the replacement method must be the same as that of the method that is replaced. Arguments will be passed and the return value of the replacement method is returned from the stubbed method. If Objective-C blocks are available a block can be used to handle the invocation and set up a return value:
If using a partial mock (see below) it is possible to forward the method to the implementation in the real object, which can be useful to simply check that a method was called:
Note that it is possible to use andReturn:, andThrow:, etc with expect, too. This will then return the given return value and, on verify, ensure that the method has been called. Argument constraints
Tells the mock object that someMethod: should be called and it does not matter what the argument is. Pointers require special treatment:
Other constraints available are:
The last constraint will, when the mock object receives someMethod:, send aSelector to anObject and if aSelector takes an argument will pass the argument that was passed to someMethod:. The method should return a boolean indicating whether the argument matched the expectation or not. If Objective-C blocks are available it is possible to check the argument with a block as follows:
Last but not least it is also possible to use Hamcrest matchers like this:
Note that this will only work when the Hamcrest framework is explicitly linked by the unit test bundle. Nice mocks / failing fastWhen a method is called on a mock object that has not been set up with either expect or stub the mock object will raise an exception. This fail-fast mode can be turned off by creating a "nice" mock:
While nice mocks will simply ignore all unexpected methods it is possible to disallow specific methods:
Note that in fail-fast mode, if the exception is ignored, it will be rethrown when verify is called. This makes it possible to ensure that unwanted invocations from notifications etc. can be detected. Protocol mocks
Creates a mock object that can be used as if it were an instance of an object that implements SomeProtocol. Partial mocks
Creates a mock object that can be used in the same way as anObject. When a method that is not stubbed is invoked it will be forwarded to anObject. When a stubbed method is invoked using a reference to anObject, rather than the mock, it will still be handled by the mock. Note that currently partial mocks cannot be created for instances of toll-free bridged classes, e.g. NSString. Observer mocks
Creates a mock object that can be used to observe notifications. The mock must be registered in order to receive notifications:
Expectations can then be set up as follows:
Note that currently there is no "nice" mode for observer mocks, they will always raise an exception when an unexpected notification is received. Instance-based method swizzlingIn a nutshell, Method Swizzling describes the replacement of a method implementation with a different implementation at runtime. Using partial mocks and the andCall: stub OCMock allows such replacements on a per-instance basis.
After these two lines, when someMethod: is sent to anObject the implementation of that method is not invoked. Instead, differentMethod: is called on differentObject. Other instances of the same class are not affected; for these the original implementation of someMethod: is still invoked. The methods can have different names but their signatures should be the same. More detailThe test cases in OCMockObjectTests and OCMockObjectHamcrestTests show all uses of OCMock. Changes.txt contains a chronological list of all changes. Logic tests and application testsApple distinguishes two different types of tests: logic tests and application tests. In a nutshell, logic tests run just like normal unit tests, but are severely limited in functionality they can use from frameworks like UIKit; trying to get a font, for example, causes a crash. Application tests are a bit harder to set up and can only run on the actual device but have full access to all functionality. For more detail on the test types and how to set them up for a project please read this section of the iOS Development Guide. OCMock fully supports both types of tests. For projects that require only logic tests the OCMock framework can be used in the same way it is used for OS X development. Detailed instructions on how to set up OCMock in this way for an iPhone project can be found in Colin Barrett's tutorial. If you need application tests you have to use the static library instead of the framework, which is described in the next few sections. OCMock static libraryThe OCMock Xcode project contains additional targets that build a static library of OCMock. When a test project links against this library (and not the framework) the OCMock classes are included in the binary itself, which means they can be run on an iOS device. The default library is built "fat", containing binary code for i386, which is required for the simulator, and armv7, which is required for running on the device. Thus, if a project requires both logic and application tests, it can do this by using the same library; the framework is not needed for either of them. To use the library in an iOS project, you have to make the actual library, ie. libOCMock.a, as well as the header files available to the project containing the tests. One way of achieving this is to copy the library and headers into a directory named "Libraries" in the project directory (this does not exist by default) and then adding the following flags to the project:
Due to some issues, which are described in this Apple Technical Q&A, you also have to add the following flags:
If you have copied the library or headers to a different place all of these settings must be adjusted accordingly. The iPhoneExample projectOCMock now contains an iPhoneExample project that shows how to use OCMock in iOS application tests. The project is set up following Apple's guidelines for application tests and the linker flags are set as described above. Note that in the Xcode inspector the path variables are expanded and the full paths are shown, as can be seen in the following screenshot. This can be confusing. ![]() At the time of writing (Xcode 3.2.3 and iOS SDK 4.0.1) there are several other issues that require very specific project settings, in particular the SDK must be set to iPhone Device 4.0 even when targeting 3.2 devices like the iPad. The following screenshot shows the settings for the example project, which is confirmed to work on the iPad despite the 4.0 SDK setting: ![]() If you have any questions or issues, please use the OCMock forum. Poking Objective-C with a Testing StickGeneral tutorial that explains in detail how to set up a project for testing with OCUnit and OCMock. Also shows how partial mocks can be used to substitute individual methods in a test. Testing Cocoa ControllersA tutorial that shows how to test Cocoa controller objects without having to load the user interface from the NIB file. The objects defined in InterfaceBuilder are replaced with mocks. Mocking Singletons with OCMockThe title says it all. Uses categories to allow substitution of system-provided singletons. Writing custom constraintsOCMock integrates with Hamcrest but sometimes it can be easier to write a constraint using the API used by OCMock's built-in constraints. This tutorial shows how it's done. Applies to iPhone and Cocoa development. OCMock and the iPhoneThis tutorial shows how to use OCMock as a framework for an iPhone project. There are some limitations to this approach. Please visit the "iPhone/iOS" tab for more information. Mocking a database connectionThis tutorial describes a classic use case for mock objects, it shows how to replace a dependency on an external call with a mock object that returns canned values. This tutorial is in German. For feedback and questions please use the OCMock forum on this site. For contributions and discussions of future development of OCMock please join the mailing list by sending an empty message to ocmock-subscribe@mulle-kybernetik.com. You can also contact me directly by email. |