Pedroinpeace
Pedroinpeace

Reputation: 1439

OCMock setup mock class, its properties and get basic understanding

I am really new into this TDD thing and writing test cases in general but I am also very eager to get into it and understand. Even though at the moment I have a very hard time to get my head around the syntax and way of thinking with stubing and mocking.

But I am also aware that I just need to get the basic hang of it to get the "aaah" moment.

Atm I am NOT there. So this very basic I know and this is my case:

I have for example a car as a class object from CoreData. The init is ofc

[MyCar alloc] initWithEntity:<(NSEntityDescription *)> insertIntoManagedObjectContext:<(NSManagedObjectContext *)>

I want to test:

- (CLLocationCoordinate2D) locationCoordinatesAtIndex: (NSInteger) index
{

CLLocationCoordinate2D returnValue
= CLLocationCoordinate2DMake(0.0f, 0.0f);

/* Sanity check */
if (index >= 0 && index < self.carsList.count)
{
    MyCar* coolCar = self.carsList[index]; //array with MyCar objects
    returnValue = CLLocationCoordinate2DMake(self.coolCar.latitude.doubleValue,
                                             self.coolCar.longitude.doubleValue);
}
return returnValue;
}

This method exist in CarViewController

So I am thinking - Ok I am gonna mock a MyCar CarViewController and and add fixed values to self.coolCar.latitude and self.coolCar.longitude doing:

@interface CarViewController
@property (nonatomic, strong) MyCar *coolCar;
@property (nonatomic, strong) NSMutableArray *carsList; //because existing private in .m
@end

@interface MyCar (Test)
@property (nonatomic, strong) NSNumber *latitude; //because existing private in .m
@property (nonatomic, strong) NSNumber *longitude; //because existing private in .m
@end

@interface WTSTestCarLocation : XCTestCase
@property (nonatomic, strong) CarViewController *carVC;
@end


-(void)testCarLoc{

self.carVC = OCMClassMock([WTSARViewController class]);`
self.coolCar = [OCMockObject mockForClass:[MyCar class]]`


self.coolCar.latitude = @7.05444;
self.coolCar.longitude = @125.601087;
[self.carsLists addObject:self.coolCar];


OCMStub([self.carVC locationCoordinatesAtIndex:0]);
/* atm I just log */
NSLog(@"the location2DLat %f",[self.carVC locationCoordinatesAtIndex:0].latitude);`

}

I get errors where the compiler says "doesNotRecognizeSelector:" failing on line

self.coolCar.latitude = @7.05444;

So Q: Do I need to do a partial mockup insted? and how would that be like with the NSEntityDescription and NSManagedObjectContext

Any help, pointers and so on is appreciated

Upvotes: 0

Views: 5651

Answers (1)

Ben Flynn
Ben Flynn

Reputation: 18922

Is it possible that latitude and longitude are read-only properties in their initial definition and don't have a setter defined?

You basically have the right idea. You should not stub the method you are actually trying to test, and generally you don't need the test to have its own member variables, you can create local variables in the test method itself.

I'd suggest this approach, notated in OCMock 3.x syntax:

-(void)testCarLoc 
{
    // Create test data
    double testLatitude = 7.05444;
    double testLongitude = 125.601087;

    // Use a partial mock for the car object to "set" its private property
    id *carPartial = OCMPartialMock([MyCar new]);
    OCMStub([carPartial latitude]).andReturn(@(testLatitude);
    OCMStub([carPartial longitude).andReturn(@(testLongitude));

    // Use a partial mock for the object under test to "set" its private property
    id *carVCPartial = OCMPartialMock([CarViewController new]);
    OCMStub([carVCPartial carsList]).andReturn(@[carPartial]);

    // Perform the action you want to test 
    CLLocationCoordinate2D result = [carVCPartial locationCoordinatesAtIndex:0];

    // Verify the results
    XCTAssertEquals(result.latitude, testLatitude);
    XCTAssertEquals(result.longitude, testLongitude);
}

Upvotes: 1

Related Questions