| --- |
| layout: minimal |
| --- |
| |
| <section id="welcome" class="group"> |
| <div id="welcomebox"> |
| <img id="logo" src="{{ site.baseurl }}/images/ocmock-504x162.png" width="252" height="81" alt="OCMock"><br> |
| <div id="welcomebox-text"> |
| <ul> |
| <li><b>Mock objects for Objective-C</b> |
| <li>Stubs – return values for specific method invocations |
| <li>Dynamic Mocks – verify interaction patterns |
| <li>Partial Mocks – overwrite methods of existing objects |
| </ul> |
| </div> |
| |
| <div id="welcomebox-buttons"> |
| <a href="{{ site.baseurl }}/download" class="button"><span class="welcomebox-btn-main">Download</span></a> |
| </div> |
| </div> |
| </section> |
| |
| |
| <section id="content" class="group"> |
| <div id="contentbox"> |
| |
| <h2>Adding OCMock to your project</h2> |
| <ul> |
| <li>Download a release from the <a href="{{ site.baseurl }}/download">downloads page</a>. |
| <li>For iOS development add the static library</a> to your test target. This is described in detail on the <a href="{{ site.baseurl }}/ios">iOS page</a>. |
| <li>For OS X development simply add <code>OCMock.framework</code> to your test target. |
| <li>Alternatively you can use Carthage or CocoaPods. |
| <li>Add an import to your unit tests. |
| </ul> |
| {% highlight objc %} |
| #import <OCMock/OCMock.h> |
| {% endhighlight objc %} |
| |
| |
| <h2>Using OCMock – the short version</h2> |
| |
| <h3>Creating stubs for instance and class methods</h3> |
| |
| <p>A mock object stands in for a real object. With stubs we can specify what to return when a method is invoked: |
| |
| {% highlight objc %} |
| // create a mock for the user defaults |
| id userDefaultsMock = OCMClassMock([NSUserDefaults class]); |
| |
| // set it up to return a specific value when stringForKey: is called |
| OCMStub([userDefaultsMock stringForKey:@"MyAppURLKey"]).andReturn(@"http://testurl"); |
| |
| // set it up to return the specified value no matter how the method is invoked |
| OCMStub([userDefaultsMock stringForKey:[OCMArg any]]).andReturn(@"http://testurl"); |
| {% endhighlight objc %} |
| |
| <p>How do we get the code that we want to test to use the mock? A pattern that is often implemented together with mocks is <a href="http://en.wikipedia.org/wiki/Dependency_injection">dependency injection</a>. With cases like <code>NSUserDefaults</code> we can take an even simpler approach. Our code under test is likely to use the standard shared instance, which is returned by the <code>standardUserDefaults</code> factory class method. We can simply stub that class method: |
| |
| {% highlight objc %} |
| // stub a class method to return our mock, and not the standard shared instance |
| OCMStub([userDefaultsMock standardUserDefaults]).andReturn(userDefaultsMock); |
| {% endhighlight objc %} |
| |
| <p>Class methods can be stubbed like instance methods. If a class has a class method and an instance method with the same name, OCMock provides a way to specify which one to target. This is described on the <a href="{{ site.baseurl }}/reference#mocking-class-methods">reference page</a>. |
| |
| |
| <h3>Verifying behaviour with a mock</h3> |
| |
| <p>Sometimes we not only want to stub a method but we want to ensure (verify) that a given method has been called by the code under test. |
| |
| {% highlight objc %} |
| // create a mock for the user defaults and make sure it's used |
| id userDefaultsMock = OCMClassMock([NSUserDefaults class]); |
| OCMStub([userDefaultsMock standardUserDefaults]).andReturn(userDefaultsMock); |
| |
| // call the code under test |
| [myController updateUserDefaults]; |
| |
| // verify it has called the expected method |
| OCMVerify([userDefaultsMock setObject:@"http://someurl" forKey:@"MyAppURLKey"]); |
| {% endhighlight objc %} |
| |
| <p>When verifying method invocations matchers can be used for the arguments in the same way as described above. |
| |
| |
| <h3>Mocking methods on an existing object: partial mocks</h3> |
| |
| <p>Sometimes we only want to stub or verify a couple of methods, but use the real implementation for all other methods. This is where partial mocks come in: |
| |
| {% highlight objc %} |
| // create an object and a partial mock for it |
| Foo *myObject = [[Foo alloc] init]; |
| id myObjectMock = OCMPartialMock(myObject); |
| |
| // replace (stub) one method on the object |
| OCMStub([myObjectMock writeToDatabase]).andReturn(@YES); |
| |
| // call the code under test |
| [myController updateDatabase] |
| |
| // verify that the method has been called |
| OCMVerify([myObjectMock writeToDatabase]); |
| {% endhighlight objc %} |
| |
| <p>It is not even necessary to stub a method in order to verify it. If we omit the stub from the code above the actual implementation of <code>writeToDatabase</code> in the object is used. We can still verify that it has been called. |
| |
| |
| <h2>Further reading</h2> |
| <p>With the examples on this page we've barely scratched the surface. OCMock has a rich feature set for many different use cases. The following pages provide good next steps to continue learning about OCMock. |
| <ul> |
| <li><a href="{{ site.baseurl }}/introduction">Getting started with OCMock</a> |
| <li><a href="{{ site.baseurl }}/reference">Reference documentation</a> |
| <li><a href="{{ site.baseurl }}/support">Tutorials</a> written by OCMock users |
| <li><a href="http://martinfowler.com/articles/mocksArentStubs.html">Mocks aren't stubs</a>, an article by Martin Fowler |
| </ul> |
| |
| <h2>Need help?</h2> |
| <p>Please ask questions on StackOverflow with the <a href="http://stackoverflow.com/questions/tagged/ocmock"><span class="tag">ocmock</span></a> tag. |
| |
| </div> |
| </section> |