Reputation: 5159
I have an objective-c class X
with method turtle
that I would like to mock with OCMock to unit test a class T
.
//X.h
@interface X
-(void) turtle;
@end
Class T
includes a category and uses that to communicate with X
. The category method calls turtle
.
//X+utils.h:
@interface X(Utils)
-(void) catMethod;
@end
//X+utils.m:
@implementation X(Utils)
-(void) catMethod
{
[self turtle];
}
@end
//T.m
#import "X+utils.h"
@implementation T
-(void) useX:(X*) xInstance
{
[xInstance catMethod];
}
In the unit test, I setup the mock such that it expects a call to turtle
.
-(void) test
{
id mockX = [OCMockObject mockForClass:[X class]]
[[mockX expect] turtle];
[instanceOfT useX:mockX];
[mockX verify];
}
I don't setup the mock to expect a call to the method of the category, since I would like to give the implementation the freedom to pick any category it likes to use.
The call useX is fails since OCMock catches the "unexpected" call to catMethod
.
Can I configure OCMock to actually use the implementation of the category and only mock calls that are defined in the actual interface X
?
Upvotes: 0
Views: 219
Reputation: 2972
Using -mockForClass: returns an object that will raise an exception on any method sent to it other than the ones you stub or expect. It does not actually have any of the implementations from the specified class; it just masquerades as an instance. -niceMockForClass: will not raise on unexpected methods, rather just those with a reject, but won't do anything either -- it is basically like a class with an empty implementation for every method.
As mentioned in the other answer, what you really want is a partial mock, which does use an actual instance of the class in question. All method calls will invoke the regular implementations except those that you stub, expect, or reject (and even with those, you can use -andForwardToRealObject to call the original implementations).
Upvotes: 0
Reputation: 6279
The key thing here is what you want to test.
In your test method you are testing useX:
, what this method does. Taking a pure unit testing approach you should just test that it calls catMethod
on x.
If you want to test that turtle is finally called you can use a partial mock like in the following code. But keep in mind this way you are not only testing T
useX:
, but also the catMethod
declared in the category.
-(void) test
{
X *x = [[X alloc] init];
id partialX = [OCMockObject partialMockForObject:x]
[[partialX expect] turtle];
[instanceOfT useX:x];
[partialX verify];
}
Upvotes: 1