Mocking a class method doesn't work !

Discussion of the OCMock framework. If you have patches we would prefer you to send them to the mailing list, but attaching them to a topic is possible, too.

Mocking a class method doesn't work !

Postby NBO » 09 Jul 2010, 15:26

Hi,
I'm trying to mock a class method.
I'm testing the GReader class, but I don't want to test the GReaderHelper class which is needed by GReader in my example.
For this, I'm using OCMock :

This is my test case file :

[code]
// File GReaderTest.m :
@implementation GReaderTest
...
- (void)testAuthentication
{
id mock = [OCMockObject mockForClass:[GReaderHelper class]];
[[[mock stub] andCall:@selector(fakeAuthenticationPost:)
onObject:self] poster:[OCMArg any]];

// I would like this line to call the fakeAuthenticationPost: method
// AND NOT the original GReaderHelper::poster method, but the mock doesn't work
// and the poster method is called
[gr authenticateWithUsername:@"dan" password:@"password"];
}
- (NSString *)fakeAuthenticationPost:(NSString *)request
{
... // Testing parameter values ...
}
@end
[/code]

And this is the tested file :
[code]
// Tested file : GReader.m

@implementation GReader
- (id)init {
self = [super init];
helper = [[GReaderHelper alloc] init];
return self;
}
- (void)authenticateWithUsername:(NSString *)username password:(NSString *)password
{
[helper poster:[NSString stringWithFormat:@"Email=%@&Passwd=%@", username, password]];
}
@end

// Class an method I WANT TO EXCLUDE from the test (using OCMock) :
@implementation GReaderHelper
- (NSString *)poster:(NSString *)request
{
...
return @"My post data";
}
@end
[/code]

There are no errors BUT MOCKING DOESN'T WORK !
The method authenticateWithUsername: calls the original poster: method, AND NOT THE TEST METHOD fakeAuthenticationPost:

Conclusion : I don't manage to use OCMock in an interesting way ... Does anyone have an idea for me ?
Thank you ...
NBO
 

Re: Mocking a class method doesn't work !

Postby erik » 20 Jul 2010, 13:11

You need to make sure that the "helper" instance variable is set to the mock object. As far as I can see from your setup the "helper" variable holds a reference to the GReaderHelper instance created in the init method.

Mock objects only deal with methods that are being sent to them; there is nothing in the framework that automatically replaces references to objects with references to mock objects. Think about it, how would the framework know what to replace?

The easiest solution in your case is to make "helper" a public settable property and add the following line to your unit test, just after creating the mock object:

Code: Select all
gr.helper = mock

If you want more background, google for "dependency injection".

By the way, this has nothing to do with class methods, all your methods are instance methods.
erik
 
Posts: 71
Joined: 10 Oct 2009, 15:22
Location: Hamburg, Germany


Return to OCMock



cron