核心数据:自定义Setter级联计算失败
我有一个名为 Location
的类,具有以下自动生成的声明,
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface Location : NSManagedObject
@property (nonatomic, retain) NSNumber * cosRadLat;
@property (nonatomic, retain) NSNumber * latitude;
@property (nonatomic, retain) NSNumber * longitude;
@property (nonatomic, retain) NSNumber * radLat;
@property (nonatomic, retain) NSNumber * radLng;
@property (nonatomic, retain) NSNumber * sinRadLat;
@end
在 Objective-C 类别中,我创建了两个方法来根据纬度和经度计算其他属性,
- (double)degreesToRadians:(NSNumber *)degrees
{
double radians = ([degrees doubleValue] * M_PI) / 180.0;
return radians;
}
- (void)setLatitude:(NSNumber *)newLat longitude:(NSNumber *)newLng
{
[self setLatitude:newLat];
[self setLongitude:newLng];
// Make calculations
double dblRadLat = [self degreesToRadians:newLat];
double dblRadLng = [self degreesToRadians:newLng];
double dblCosRadLat = cos(dblRadLat);
double dblSinRadLat = sin(dblRadLat);
// and set their values
[self setRadLat:[NSNumber numberWithDouble:dblRadLat]];
[self setRadLng:[NSNumber numberWithDouble:dblRadLng]];
[self setCosRadLat:[NSNumber numberWithDouble:dblCosRadLat]];
[self setSinRadLat:[NSNumber numberWithDouble:dblSinRadLat]];
}
当我运行单元测试时,一半的时间我会得到这样的信息:
Lat 40.7302133
Lng -74.0003337
RadLat 0.7108763271245849
RadLng -1.291549470639518
CosRadLat 0.7577903652576623
SinRadLat 0.6524980937310535
另一半的时间我会得到这样的信息:
Lat 40.7302133
Lng -74.0003337
RadLat 0
RadLng 0
CosRadLat 0
SinRadLat 0
我做错了什么?
单元测试
这是我用来在单元测试中保存上下文的函数,
- (void)saveContext
{
NSLog(@"%@ saveContext", self.name);
NSError *saveError = nil;
STAssertTrue([self.managedObjectContext save:&saveError], @"Failed to save context to persistent store: %@", saveError);
}
这就是我如何调用它,
// Constants we will check to ensure our calcluations are correct
// 1st Location
double const LAT = 40.7292540;
double const LNG = -73.9988530;
double const RAD_LAT = 0.710859584;
double const RAD_LNG = -1.29152363;
double const SIN_RAD_LAT = 0.652485406;
double const COS_RAD_LAT = 0.75780129;
double const accuracy = 0.00000001;
/** Run before each test. Populates the database with objects to play with.
*/
- (void)setUp
{
NSLog(@"%@ setUp", self.name);
// Creates our persistent store in memory and initializes our managed object context for us.
[super setUp];
// Create a new Location
Location *location = [NSEntityDescription insertNewObjectForEntityForName:@"Location" inManagedObjectContext:self.managedObjectContext];
// Using the setLatitude:longitude: method, which cascades the calculation for all other values
[location setLatitude:[NSNumber numberWithDouble:LAT] longitude:[NSNumber numberWithDouble:LNG]];
// Check if it has properly calculated the values we asked for
double lat = [[location latitude] doubleValue];
double lng = [[location longitude] doubleValue];
double rad_lat = [[location radLat] doubleValue];
double rad_lng = [[location radLng] doubleValue];
double sin_rad_lat = [[location sinRadLat] doubleValue];
double cos_rad_lat = [[location cosRadLat] doubleValue];
STAssertEqualsWithAccuracy(LAT, lat, accuracy, @"Wanted: %f Got: %f", LAT, lat);
STAssertEqualsWithAccuracy(LNG, lng, accuracy, @"Wanted: %f Got: %f", LNG, lng);
STAssertEqualsWithAccuracy(RAD_LAT, rad_lat, accuracy, @"Wanted: %f Got: %f", RAD_LAT, rad_lat);
STAssertEqualsWithAccuracy(RAD_LNG, rad_lng, accuracy, @"Wanted: %f Got: %f", RAD_LNG, rad_lng);
STAssertEqualsWithAccuracy(SIN_RAD_LAT, sin_rad_lat, accuracy, @"Wanted: %f Got: %f", SIN_RAD_LAT, sin_rad_lat);
STAssertEqualsWithAccuracy(COS_RAD_LAT, cos_rad_lat, accuracy, @"Wanted: %f Got: %f", COS_RAD_LAT, cos_rad_lat);
// Saves the managed object context into the persistent store.
[self saveContext];
}
这部分通常可以工作。发生的情况是,setup
被调用,它运行这个测试,而这里就是失败的地方,
- (Location *)fetchLastLocation
{
NSLog(@"%@ getLastLocation", self.name);
NSMutableArray *mutableFetchResults = [self fetchEntity: @"Location"];
Location *location = (Location *)[mutableFetchResults lastObject];
return location;
}
/** Tests to see if the values stick after saving and fetching
*/
- (void)testCalculatedValuesStick
{
Location *location = [self fetchLastLocation];
NSLog(@"Stick: %@", location);
// Check if it has properly calculated the values we asked for
double lat = [[location latitude] doubleValue];
double lng = [[location longitude] doubleValue];
double rad_lat = [[location radLat] doubleValue];
double rad_lng = [[location radLng] doubleValue];
double sin_rad_lat = [[location sinRadLat] doubleValue];
double cos_rad_lat = [[location cosRadLat] doubleValue];
STAssertEqualsWithAccuracy(LAT, lat, accuracy, @"Wanted: %f Got: %f", LAT, lat);
STAssertEqualsWithAccuracy(LNG, lng, accuracy, @"Wanted: %f Got: %f", LNG, lng);
STAssertEqualsWithAccuracy(RAD_LAT, rad_lat, accuracy, @"Wanted: %f Got: %f", RAD_LAT, rad_lat);
STAssertEqualsWithAccuracy(RAD_LNG, rad_lng, accuracy, @"Wanted: %f Got: %f", RAD_LNG, rad_lng);
STAssertEqualsWithAccuracy(SIN_RAD_LAT, sin_rad_lat, accuracy, @"Wanted: %f Got: %f", SIN_RAD_LAT, sin_rad_lat);
STAssertEqualsWithAccuracy(COS_RAD_LAT, cos_rad_lat, accuracy, @"Wanted: %f Got: %f", COS_RAD_LAT, cos_rad_lat);
}
你认为我的单元测试与它有什么关系吗?
I have a class called Location
with the following automatically generated declaration,
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface Location : NSManagedObject
@property (nonatomic, retain) NSNumber * cosRadLat;
@property (nonatomic, retain) NSNumber * latitude;
@property (nonatomic, retain) NSNumber * longitude;
@property (nonatomic, retain) NSNumber * radLat;
@property (nonatomic, retain) NSNumber * radLng;
@property (nonatomic, retain) NSNumber * sinRadLat;
@end
In an objective-c category, I have created two methods to calculate the other properties based on the latitude and longitude,
- (double)degreesToRadians:(NSNumber *)degrees
{
double radians = ([degrees doubleValue] * M_PI) / 180.0;
return radians;
}
- (void)setLatitude:(NSNumber *)newLat longitude:(NSNumber *)newLng
{
[self setLatitude:newLat];
[self setLongitude:newLng];
// Make calculations
double dblRadLat = [self degreesToRadians:newLat];
double dblRadLng = [self degreesToRadians:newLng];
double dblCosRadLat = cos(dblRadLat);
double dblSinRadLat = sin(dblRadLat);
// and set their values
[self setRadLat:[NSNumber numberWithDouble:dblRadLat]];
[self setRadLng:[NSNumber numberWithDouble:dblRadLng]];
[self setCosRadLat:[NSNumber numberWithDouble:dblCosRadLat]];
[self setSinRadLat:[NSNumber numberWithDouble:dblSinRadLat]];
}
When I run my unit tests, half the time I get this:
Lat 40.7302133
Lng -74.0003337
RadLat 0.7108763271245849
RadLng -1.291549470639518
CosRadLat 0.7577903652576623
SinRadLat 0.6524980937310535
The other half, I get this:
Lat 40.7302133
Lng -74.0003337
RadLat 0
RadLng 0
CosRadLat 0
SinRadLat 0
What am I doing wrong?
UNIT TEST
Here is my function I use to save the context in the unit test,
- (void)saveContext
{
NSLog(@"%@ saveContext", self.name);
NSError *saveError = nil;
STAssertTrue([self.managedObjectContext save:&saveError], @"Failed to save context to persistent store: %@", saveError);
}
And here is how I am calling it,
// Constants we will check to ensure our calcluations are correct
// 1st Location
double const LAT = 40.7292540;
double const LNG = -73.9988530;
double const RAD_LAT = 0.710859584;
double const RAD_LNG = -1.29152363;
double const SIN_RAD_LAT = 0.652485406;
double const COS_RAD_LAT = 0.75780129;
double const accuracy = 0.00000001;
/** Run before each test. Populates the database with objects to play with.
*/
- (void)setUp
{
NSLog(@"%@ setUp", self.name);
// Creates our persistent store in memory and initializes our managed object context for us.
[super setUp];
// Create a new Location
Location *location = [NSEntityDescription insertNewObjectForEntityForName:@"Location" inManagedObjectContext:self.managedObjectContext];
// Using the setLatitude:longitude: method, which cascades the calculation for all other values
[location setLatitude:[NSNumber numberWithDouble:LAT] longitude:[NSNumber numberWithDouble:LNG]];
// Check if it has properly calculated the values we asked for
double lat = [[location latitude] doubleValue];
double lng = [[location longitude] doubleValue];
double rad_lat = [[location radLat] doubleValue];
double rad_lng = [[location radLng] doubleValue];
double sin_rad_lat = [[location sinRadLat] doubleValue];
double cos_rad_lat = [[location cosRadLat] doubleValue];
STAssertEqualsWithAccuracy(LAT, lat, accuracy, @"Wanted: %f Got: %f", LAT, lat);
STAssertEqualsWithAccuracy(LNG, lng, accuracy, @"Wanted: %f Got: %f", LNG, lng);
STAssertEqualsWithAccuracy(RAD_LAT, rad_lat, accuracy, @"Wanted: %f Got: %f", RAD_LAT, rad_lat);
STAssertEqualsWithAccuracy(RAD_LNG, rad_lng, accuracy, @"Wanted: %f Got: %f", RAD_LNG, rad_lng);
STAssertEqualsWithAccuracy(SIN_RAD_LAT, sin_rad_lat, accuracy, @"Wanted: %f Got: %f", SIN_RAD_LAT, sin_rad_lat);
STAssertEqualsWithAccuracy(COS_RAD_LAT, cos_rad_lat, accuracy, @"Wanted: %f Got: %f", COS_RAD_LAT, cos_rad_lat);
// Saves the managed object context into the persistent store.
[self saveContext];
}
This part usually works. What happens is, setup
is called, it runs this test, and here is where it fails,
- (Location *)fetchLastLocation
{
NSLog(@"%@ getLastLocation", self.name);
NSMutableArray *mutableFetchResults = [self fetchEntity: @"Location"];
Location *location = (Location *)[mutableFetchResults lastObject];
return location;
}
/** Tests to see if the values stick after saving and fetching
*/
- (void)testCalculatedValuesStick
{
Location *location = [self fetchLastLocation];
NSLog(@"Stick: %@", location);
// Check if it has properly calculated the values we asked for
double lat = [[location latitude] doubleValue];
double lng = [[location longitude] doubleValue];
double rad_lat = [[location radLat] doubleValue];
double rad_lng = [[location radLng] doubleValue];
double sin_rad_lat = [[location sinRadLat] doubleValue];
double cos_rad_lat = [[location cosRadLat] doubleValue];
STAssertEqualsWithAccuracy(LAT, lat, accuracy, @"Wanted: %f Got: %f", LAT, lat);
STAssertEqualsWithAccuracy(LNG, lng, accuracy, @"Wanted: %f Got: %f", LNG, lng);
STAssertEqualsWithAccuracy(RAD_LAT, rad_lat, accuracy, @"Wanted: %f Got: %f", RAD_LAT, rad_lat);
STAssertEqualsWithAccuracy(RAD_LNG, rad_lng, accuracy, @"Wanted: %f Got: %f", RAD_LNG, rad_lng);
STAssertEqualsWithAccuracy(SIN_RAD_LAT, sin_rad_lat, accuracy, @"Wanted: %f Got: %f", SIN_RAD_LAT, sin_rad_lat);
STAssertEqualsWithAccuracy(COS_RAD_LAT, cos_rad_lat, accuracy, @"Wanted: %f Got: %f", COS_RAD_LAT, cos_rad_lat);
}
Do you think my unit test has anything to do with it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我注意到你的方法正在创建名为 radLat 的变量,但这也是你的实例的属性 - 我觉得你可能会遇到指针问题。
尝试将方法变量的名称(
double radLat
等)更改为不同的名称,看看这是否会改变代码的运行方式。我认为该代码的行为方式并不符合您的预期 - 尽管了解有关Location
类上操作的代码的更多信息会有所帮助。I noticed your method is making variables named radLat, but that is also a property of your instance - I feel like you may have pointer troubles happening.
Try changing the name of your method variables (
double radLat
etc) to something different and see if that changes how your code is running. I think that code isn't behaving the way you're expecting it to - though knowing more about the code operating on yourLocation
class will help.