1

I'm trying to create a mock for AFNetworking's AFHTTPRequestOperationManager using OCMock

This is what I've got:

id mockRequestManager = OCMClassMock([AFHTTPRequestOperationManager class]);
OCMStub([mockRequestManager manager]).andReturn(mockRequestManager);
[myObject methodThatUsesAFHTTPRequestOperationManager];

I've done this exact thing before for other singletons ([NSNotificationCenter defaultCenter] for example), but with AFHTTPRequestOperationManager, I'm not getting back the mocked object when [AFHTTPRequestOperationManager manager] is called from [myObject methodThatUsesAFHTTPRequestOperationManager]. I always get back the AFHTTPRequestOperationManager instance object.

Am I missing something? Is there some implementation detail of AFHTTPRequestOperationManager that's preventing this from working?

EDIT

So, after looking through the AFHTTPRequestOperationManager code, it turns out it's not actually a singleton, just a class method that returns a new AFHTTPRequestOperationManager object. However, I still don't understand why stubbing the class method isn't returning the my mock object instead of creating a new one.

Jordan
  • 4,133
  • 1
  • 27
  • 43

1 Answers1

0

As you say is not a singleton. You can inject it instead; have a look to this answer.

Using injection is preferred over singletons. In case you don't want to inject typical objects like [NSNotificationCenter defaultCenter] of [NSUserDefaults standardUserDefaults] what you can do instead of mocking and stubbing the shared instance accessor is just use the real object in your tests. For instance, instead of testing that you are posting a particular notification mocking the defaulCenter, you could listen to that notification in you test. I like this solution more since it avoids using mocks and we could say that is more reliable since you are testing your object in conjunction with the real notification center. Some people may say that then the test would be an integration test but IMO is not worth to make any distinction in this case.

About stubbing the shared instance accessor, I am not used to the new OCMock syntax but there shouldn't be a problem with that, check out how to stub a class method with OCMock.

Community
  • 1
  • 1
e1985
  • 6,239
  • 1
  • 24
  • 39
  • I saw that other post while trying to research this issue. I don't have a problem stubbing other class methods, just this one in particular. I could opt to inject the AFHTTPRequestOperationManager object, but that would put the responsibility of creating the object on another class in the project just for the sake of being able to test this class. My reason for wanting to mock this in the first place is the intercept GET:parameters:success:failure: so my test doesn't rely on an actual networking call. I don't know of a way to observe this, like you can with notification posts. – Jordan Aug 29 '14 at 15:05
  • 1
    IMO having a class responsible of creating and managing the lifecycle or your objects is a nice thing to have, as it helps you to separate glue code from business logic. Apart from that, check out Nocilla(https://github.com/luisobo/Nocilla), a library to stub network calls with ease. With it you can test your code without the need of mocking the AFHTTPRequestOperationManager. – e1985 Aug 30 '14 at 11:04