Reputation: 1439
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
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