本单元测试代码的不一致之处

时间:2013-12-06 21:35:50

标签: ios objective-c unit-testing mapping restkit

我正在尝试清理我写的单元测试。

@implementation CTFUserTests {
    CoreDataService *_service;
    RKObjectManager *_manager;
    CTFAPIMappings *_mapping;
}

- (void)setUp {
    _service = [[CoreDataService alloc] initForUnitTesting];

    _manager = [[RKObjectManager alloc] init];
    RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:_service.managedObjectModel];
    _manager.managedObjectStore = managedObjectStore;

    NSBundle *bundle = [NSBundle bundleWithIdentifier:[[NSBundle mainBundle].bundleIdentifier stringByAppendingString:@"Tests"]];
    [RKTestFixture setFixtureBundle:bundle];

    _mapping = [[CTFAPIMappings alloc] initWithManager:_manager];

    [super setUp];
}

- (void)tearDown {
    _service = nil;
    _manager = nil;
    [super tearDown];
}

这是返回RKEntityMapping的方法:

- (RKEntityMapping *)simpleUserMapping {
    RKEntityMapping *userMapping =
    [RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFUser class]) inManagedObjectStore:_mapping.manager.managedObjectStore];
    [userMapping addAttributeMappingsFromDictionary:[_mapping userMappingDict]];
    return userMapping;
}

以下是测试:

- (void)testUserResponseMApping {
    id parsedJSON = [RKTestFixture parsedObjectWithContentsOfFixture:@"user-response.json"];

    /// Configure mapping
    RKEntityMapping *userMapping = [self simpleUserMapping];

    RKMappingTest *test = [RKMappingTest testForMapping:userMapping sourceObject:parsedJSON destinationObject:nil];
    test.managedObjectContext = _service.managedObjectContext;

    RKPropertyMappingTestExpectation *usernameExpectation =
    [RKPropertyMappingTestExpectation expectationWithSourceKeyPath:@"username" destinationKeyPath:@"username" value:@"tomkowz12"];
    [test addExpectation:usernameExpectation];
    [test verify];

这里一切都好。测试通过。 但我想要的是创建一些类,我可以定义并返回调用服务器所需的所有映射。它听起来像是映射的单例。所以就是这样。

@interface CTFAPIMappings : NSObject

@property (readonly) RKObjectManager *manager;

+ (instancetype)sharedInstance;
+ (void)setSharedInstance:(CTFAPIMappings *)sharedInstance;
- (instancetype)initWithManager:(RKObjectManager *)manager;
- (RKEntityMapping *)userMapping;
- (NSDictionary *)userMappingDict;
@end

-userMapping方法的实现与单元测试类中的上述方法-simpleUserMapping相同。如上所述,方法-simpleUserMapping使用的_mapping对象类型为CTFAPIMappings。因此CTFAPIMappings的方法也是如此,但使用self而不是_mapping

@implementation CTFAPIMappings
…
- (RKEntityMapping *)userMapping {
    RKEntityMapping *userMapping =
    [RKEntityMapping mappingForEntityForName:NSStringFromClass([CTFUser class]) inManagedObjectStore:_manager.managedObjectStore];
    [userMapping addAttributeMappingsFromDictionary:[self userMappingDict]];
    return userMapping;
}

CTFAPIMappings对象初始化时使用RKObjectManager方法初始化-setUp。所以它与测试方法中的RKObjectManager相同。当我替换时,问题出现在testUserResponseMapping方法中:

    RKEntityMapping *userMapping = [self simpleUserMapping];

使用:

    RKEntityMapping *userMapping = [_mapping userMapping];

并在-performMapping类中的方法RKMappingTest上测试崩溃:

        [NSException raise:NSInternalInconsistencyException format:@"%p: failed with error: %@\n%@ during mapping from %@ to %@ with mapping %@",

崩溃日志如下所示:

<unknown>:0: error: -[CTFUserTests testUserResponseMApping] : 0x8d96f30: failed with error: (null)
RKMappingTest Expectations: (
    "map 'username' to 'username' with __NSCFConstantString value 'tomkowz12'"
)
Events: (
) during mapping from <CFBasicHash 0x8d7ef90 [0x2267ec8]>{type = immutable dict, count = 5,
entries =>
    1 : <CFString 0x8d70d00 [0x2267ec8]>{contents = "password"} = <CFString 0x8d70d20 [0x2267ec8]>{contents = "password123"}
    2 : <CFString 0x8d76bb0 [0x2267ec8]>{contents = "username"} = <CFString 0x8d76600 [0x2267ec8]>{contents = "tomkowz12"}
    3 : <CFString 0x8d7d160 [0x2267ec8]>{contents = "location"} = <CFArray 0x8d7ef70 [0x2267ec8]>{type = immutable, count = 2, values = (
    0 : <CFNumber 0x8faef40 [0x2267ec8]>{value = +10, type = kCFNumberSInt32Type}
    1 : <CFNumber 0x8d7d180 [0x2267ec8]>{value = +20, type = kCFNumberSInt64Type}
)}
    4 : <CFString 0x8d94f50 [0x2267ec8]>{contents = "email"} = <CFString 0x8d76620 [0x2267ec8]>{contents = "tmk.szlc@gmail.com"}
    6 : <CFString 0x8d92860 [0x2267ec8]>{contents = "nick"} = <CFString 0x8d7d140 [0x2267ec8]>{contents = "black_lord"}
}
 to (null) with mapping <RKEntityMapping:0x8d7a8d0 objectClass=CTFUser propertyMappings=(
    "<RKAttributeMapping: 0x8d7a300 password => password>",
    "<RKAttributeMapping: 0x8d732b0 username => username>",
    "<RKAttributeMapping: 0x8d77fe0 location => location>",
    "<RKAttributeMapping: 0x8d95db0 email => email>",
    "<RKAttributeMapping: 0x8d7ce60 nick => nick>"
)>
(
    0   CoreFoundation                      0x0211c5e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x01e9f8b6 objc_exception_throw + 44
    2   CoreFoundation                      0x0211c3bb +[NSException raise:format:] + 139
    3   Capture The FlagTests               0x098f08ab -[RKMappingTest performMapping] + 1067
    4   Capture The FlagTests               0x098f0f53 -[RKMappingTest verify] + 99
    5   Capture The FlagTests               0x09801e35 -[CTFUserTests testUserResponseMApping] + 517
    6   CoreFoundation                      0x02110d1d __invoking___ + 29
    7   CoreFoundation                      0x02110c2a -[NSInvocation invoke] + 362
    8   XCTest                              0x201032bf -[XCTestCase invokeTest] + 212
    9   XCTest                              0x2010338d -[XCTestCase performTest:] + 111
    10  XCTest                              0x2010417c -[XCTest run] + 82
    11  XCTest                              0x20102a44 -[XCTestSuite performTest:] + 139
    12  XCTest                              0x2010417c -[XCTest run] + 82
    13  XCTest                              0x20102a44 -[XCTestSuite performTest:] + 139
    14  XCTest                              0x2010417c -[XCTest run] + 82
    15  XCTest                              0x20102a44 -[XCTestSuite performTest:] + 139
    16  XCTest                              0x2010417c -[XCTest run] + 82
    17  XCTest                              0x20105aa1 +[XCTestProbe runTests:] + 183
    18  Foundation                          0x01ad612c __NSFireDelayedPerform + 372
    19  CoreFoundation                      0x020dabd6 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
    20  CoreFoundation                      0x020da5bd __CFRunLoopDoTimer + 1181
    21  CoreFoundation                      0x020c2628 __CFRunLoopRun + 1816
    22  CoreFoundation                      0x020c1ac3 CFRunLoopRunSpecific + 467
    23  CoreFoundation                      0x020c18db CFRunLoopRunInMode + 123
    24  GraphicsServices                    0x03ae29e2 GSEventRunModal + 192
    25  GraphicsServices                    0x03ae2809 GSEventRun + 104
    26  UIKit                               0x00c0dd3b UIApplicationMain + 1225
    27  Capture The Flag                    0x0000a27d main + 141
    28  libdyld.dylib                       0x0275a70d start + 1
    29  ???                                 0x00000008 0x0 + 8
)

我花了大约4个小时的时间,并没有看到任何我错过的东西。对我来说一切都很好,但测试没有通过。我的清理有什么问题?我错过了什么?

提前谢谢。

修改

我在测试中创建的注释为RKOBjectManager实例的等式CTFAPIMappings添加以下测试。

- (void)testInstanceShouldHaveTheSameManagerAndStoreAsInjected {
    RKObjectManager *objectManager = [[RKObjectManager alloc] init];
    RKManagedObjectStore *store = [[RKManagedObjectStore alloc] initWithPersistentStoreCoordinator:_service.persistentStoreCoordinator];
    [store createManagedObjectContexts];

    objectManager.managedObjectStore = store;

    CTFAPIMappings *mappings = [[CTFAPIMappings alloc] initWithManager:objectManager];
    XCTAssertNotNil(mappings, @"");
    XCTAssertNotNil(mappings.manager, @"");
    XCTAssertEqualObjects(mappings.manager, objectManager, @"");
    XCTAssertEqualObjects(mappings.manager.managedObjectStore, objectManager.managedObjectStore, @"");
}

这是一个简单的测试,它检查两个映射的相等性(对象是否相等):

RKEntityMapping *localCharacterMapping = [self userMapping];
RKEntityMapping *mappingsCharacterMapping = [_mappings userMapping];

XCTAssertEqualObjects(localCharacterMapping.entity, mappingsCharacterMapping.entity, @"");
XCTAssertEqualObjects(localCharacterMapping.persistentStore, mappingsCharacterMapping.persistentStore, @"");

NSLog(@"local = %@", localCharacterMapping);
NSLog(@"mappi = %@", mappingsCharacterMapping);

并记录:

2013-12-07 15:12:07.094 Capture The Flag[27712:70b] local = <RKEntityMapping:0x8ee9ac0 objectClass=CTFUser propertyMappings=(
"<RKAttributeMapping: 0x8e91c00 password => password>",
"<RKAttributeMapping: 0x8ebeb50 username => username>",
"<RKAttributeMapping: 0x8ecb830 location => location>",
"<RKAttributeMapping: 0x8e94730 email => email>",
"<RKAttributeMapping: 0x8ec5d90 nick => nick>",
"<RKRelationshipMapping: 0x8eebef0 characters => characters>"
)>
2013-12-07 15:12:07.096 Capture The Flag[27712:70b] mappi = <RKEntityMapping:0x8eec060 objectClass=CTFUser propertyMappings=(
"<RKAttributeMapping: 0x8eed020 password => password>",
"<RKAttributeMapping: 0x8e8a910 username => username>",
"<RKAttributeMapping: 0x8eb5a30 location => location>",
"<RKAttributeMapping: 0x8e86620 email => email>",
"<RKAttributeMapping: 0x8e92490 nick => nick>",
"<RKRelationshipMapping: 0x8eee3d0 characters => characters>"
)>

1 个答案:

答案 0 :(得分:0)

好的,我查了一下。问题出在Cocoapods。在家里,我0.22,在办公室,我有0.27。更新到0.28之后,更新pod之后一切正常。 - Tomasz Szulc刚刚编辑