How to Create Mocks and Stubs in Swift

Without 100% support for a mocking framework like OCMock, I found myself needing to get creative when building mock objects and method stubs in Swift unit tests.  The great thing about testing is that you’re…well… testing things out to see if they’ll work, and I found a solution that I’m pretty happy with for now.  I’m open to better ways, so leave a comment if you’ve had good results using a different design!

The process is essentially this (example to follow):

  1. Ensure that the class that you would like to test is designed so that you can substitute your mock for the real one that’s used in your class’ implementation
  2. Create an XCTestCase  class with a test function in your unit test project
  3. Within the function body create a nested class
  4. Make the nested class inherit from the real object you’re trying to mock / create a method stub for
  5. You can give the nested class a name such as Mock[ObjectName]
  6. Configure the mock object however you need by setting its properties or overriding its function implementations with stubbed implementations – no need to override every function… only the one(s) that your class calls during the test at hand
  7. Instantiate the class you’re testing and pass in an instance of the mock object you just nested in the test function to your class somehow (either through its initializer, by setting a property on the class, or by passing it into the method under test via parameter — however you intended to ‘inject’ the mock from step 1 is what you should do)
  8. XCTAssert…

Let’s see those 8 steps in action for those of us who are more visually inclined.

EDIT:  July 22, 2014 – I’ve added a simple XCode Project to GitHub for those interested in seeing the setup directly in XCode at  https://github.com/andrewcbancroft/MocksAndStubs

The scenario that I’d like to use a mock class in is this:  I have a CoreData application and I’d like to be able to mock the NSManagedObjectContext  so that instead of making actual database fetch requests, I can just provide stubs of various sorts with the kinds of responses I’d expect from the real database calls to ensure my class will do the right thing based on predictable results.  To do this I begin at step 1…

1.  Ensure that the class that you would like to test is designed so that you can substitute your mock for the real one that’s used in your class’ implementation

In the example class below, I intend to provide the NSManagedObjectContext  dependency through the class’ initializer which will set a property that is used by my class’ methods later on, but you could easily use some other way of performing “dependency injection”.  The initializer strategy just makes it super clear in my mind what the class’ dependencies are, so that’s what I’m going to do here.  Have a look:

Now, let’s say that my example class has a member function called  databaseHasRecordsForSomeEntity  that returns a Bool  value of true if the resulting array of a fetch request contains objects, and a Bool  value of false if the result array of a fetch request is empty.  The completed class looks like this:

I want to test if  databaseHasRecordsForSomeEntity  does what I intend it to do. So…

2.  Create an  XCTestCase  class with a test function in your unit test project

Just listing this for completeness

Next comes the way to make the mock.  Read steps 3-5 and then look below for a code example of what the skeleton will look like.

3.  Within the function body create a nested class

4.  Make the nested class inherit from the real object you’re trying to mock / create a method stub for

5.  You can give the nested class a name such as Mock[ObjectName]

 6.  Configure the mock object however you need by setting its properties or overriding its function implementations with stubbed implementations – no need to override every function… only the one(s) that your class calls during the test at hand

For my example, I’m going to stub out the executeFetchRequest  method so that it returns an array with one object in it.  This is really the part where you have to determine what you’re testing and what you expect the stubbed results to be.  Whatever you decide, the way to stub a method is simply to override it in the mock you’re implementing.  Here’s how I implemented the  executeFetchRequest  stub for my example:

We’re ready to perform the test and assert the results.  Read steps 7-8 and take a look at the code example below step 8:

7.  Instantiate the class you’re testing and pass in an instance of the mock object you just nested in the test function to your class somehow (either through its initializer, by setting a property on the class, or by passing it into the method under test via parameter — however you intended to ‘inject’ the mock from step 1 is what you should do)

8.  XCTAssert…

From step 1, I intended to pass an NSManagedObjectContext instance to the initializer of MyClass, so that’s what I’ll do in my test.  I’ll then perform the XCTAssert on the return value of my method under test:

 

Running the tests at this point should produce a passing test using the mock object in place of a real NSManagedObjectContext that calls a database!

Now, if I wanted to test the “false” branch of my class’ method, I could simply create another test method following the same steps, only this time, I’d provide a new implementation for the overridden executeFetchRequest  method that’s appropriate:

And that’s a wrap – happy mocking and stubbing in Swift!

EDIT:  July 22, 2014 – I’ve added a simple XCode Project to GitHub for those interested in seeing the setup directly in XCode at  https://github.com/andrewcbancroft/MocksAndStubs