Question

I am new to OCMockObjects and trying to mock an instance method of ACAccount class:

-(NSArray *)accountsWithAccountType:(ACAccountType *)accountType;

I wrote this code in the test class to intialize mockObject:

ACAccountStore *accountStore = [[ACAccountStore alloc] init];
id mockAccountStore = [OCMockObject partialMockForObject:accountStore];
[[[mockAccountStore stub] andReturn:@[@"someArray"]] accountsWithAccountType:[OCMArg any]];

//call the test method
[myClassInstance methodToTest];

In myClass the methodToTest looks like this:

 -(void) methodToTest
{
    ACAccountStore *accountStore = [[ACAccountStore alloc] init];
    ACAccountType* accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
    NSArray* expectedArray = [accountStore accountsWithAccountType:accountType];
   //Getting nil value to Array rather than the returned value in stub
}

Any idea what am i doing wrong here. Thanks.

Was it helpful?

Solution 2

You are creating a mock, but the method you are testing is not using the mock, it's using an instance of the original ACAccountStore class.

If you are willing, the easiest way to make methodToTest testable is to have it accept an instance of ACAccountStore as an argument.

- (void)methodToTestWithAccountStore:(ACAccountStore *)accountStore;

Then your test looks like this:

[myClassInstance methodToTest:mockAccountStore];

This would follow a dependency injection pattern. If you don't like this pattern, you could mock the alloc method of ACAccountStore to return your mock object, but I am always wary of possible side-effects from mocking alloc and instead would suggest creating a factory for ACAccountStore:

@interface ACAccountStore (Factory)
+ (instancetype)accountStore;
@end
@implementation ACAccountStore
+ (instancetype)accountStore { return [[ACAccountStore alloc] init]; }
@end

If you use this pattern, you can mock your factory method.

OTHER TIPS

Ben Flynn is correct that you need a way to inject an AccountStore into the object you're testing. Two additional ways to do this:

1) Make accountStore a property of the class under test that gets set at initialization, then override that property with a mock in your test.

2) Create a method like -(ACAccountStore *)accountStore that initializes the account store, but in your test mock that method:

ACAccountStore *accountStore = [[ACAccountStore alloc] init];
id mockAccountStore = [OCMockObject partialMockForObject:accountStore];
[[[mockAccountStore stub] andReturn:@[@"someArray"]] accountsWithAccountType:[OCMArg any]];

id mockInstance = [OCMockObject partialMockForObject:myClassInstance];
[[[mockInstance stub] andReturn:mockAccountStore] accountStore];

// call the test method
[myClassInstance methodToTest];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top