4
votes

I am new in OCMock.

I use dispatch_once() created a singleton class MyManager :

@implementation MyManager

+ (id)sharedInstance {
    static MyManager *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedMyManager = [[self alloc] init];
    });
    return sharedMyManager;
}

I have a method in School class which uses the above singleton:

@implementation School
...
- (void) createLecture {
  MyManager *mgr = [MyManager sharedInstance];
  [mgr checkLectures];
  ...
}
@end

Now, I want to unit test this method, I use a partial mock of MyManager:

- (void) testCreateLecture {
  // create a partially mocked instance of MyManager
  id partialMockMgr = [OCMockObject partialMockForObject:[MyManager sharedInstance]];

  // run method to test
  [schoolToTest createLecture];
  ...
}

I noticed that with OCMock, after I created the partial mock of my singleton MyManager instance, when run my method under test, it automatically use the partially mocked instance.

This is a bit weird to me, since in my test case above, I only created the partial mock of MyManager instance without injecting it to MyManager class,

how does OCMock automatically force the code under test use this mocked instance when [MyManager sharedInstance] is called in the code under test ? Could someone explain to me this?

2

2 Answers

4
votes

partialMockForObject mocks the object you are passing to it.

In this case you are mocking the singleton (shared) object. You don't have to inject anything because sharedInstance is always returning the same object, now mocked. It is still the same reference.

Imagine partial mocking as a simple mutation of the passed object, it doesn't create a new instance so you don't have to inject it in this specific case.

2
votes

Partial Mocks are pretty cool. Behind the scenes, OCMock subclasses the class you are mocking, and any method that you stub is updated in the partial mock subclass. So all references to your mocked class will now default to the subclass (mocked implementation) instead of the superclass (your implementation). There's a good explanation in the reference on this as well.