如何使用 OCMock 模拟服务

How to use OCMock to mock a service

我正在尝试编写一个单元测试来创建一个 checklistItem,其属性定义如下:

typedef NS_ENUM (NSUInteger, ChecklistStatus) { Pending, Completed };
@protocol IChecklistItem <NSObject>
@property (nonatomic, assign, readonly) NSInteger Id;
@property (nonatomic, copy, readonly) NSString *Description;
@property (nonatomic, assign, readonly)BOOL IsCompleted;
@property (nonatomic, assign, readwrite) ChecklistStatus Status;
@property (nonatomic, strong, readwrite) NSDate *CompletedDate;
@property (nonatomic, copy, readwrite) NSString *CompletedByUserId;
@property (nonatomic, assign, readonly) NSInteger RoleId;
@property (nonatomic, assign, readonly) NSInteger GroupId;
@property (nonatomic, strong, readonly) NSArray<IChecklistNote> *Notes;

现在我在 XCTest 的设置方法中进行了此设置:

_service = [[ChecklistService alloc]initWithUrl:[NSURL URLWithString:kcChecklistUrl] credentialsManager:self.credentialsManager];

这是我的单元测试的其余部分:

- (void)testCreateChecklistItem {
    XCTAssertNotNil(_service);
    CCChecklistItem *checklistItem = [CCChecklistItem new];
    CCChecklistItem *newChecklistItem = [CCChecklistItem new];
    newChecklistItem.Id = 2;
    newChecklistItem.Description = @"This is the Description";
    newChecklistItem.RoleId = 2;
    newChecklistItem.GroupId = 3;
    newChecklistItem.Notes = nil;
    newChecklistItem.Status = Completed;

    XCTestExpectation *checklistItemExpectation = [self expectationWithDescription:@"checklistItem"];

    id delegate = OCMProtocolMock(@protocol(ChecklistServiceDelegate));
    id mock = [OCMockObject mockForProtocol:(@protocol(IChecklistService))];
    [[[mock stub] andReturn:newChecklistItem] createChecklistItem:checklistItem delegate:delegate];

    OCMExpect(([delegate didCompleteCreateChecklistItem:[OCMArg checkWithBlock:^BOOL(id obj) {
        CCChecklistItem *items = obj;
        XCTAssertNotNil(items);
        double checklistId = items.Id;
        XCTAssert(checklistId != 0);
        [checklistItemExpectation fulfill];
    }]]));

    [_service createChecklistItem:checklistItem delegate:delegate];
    [self waitForExpectationsWithTimeout:5 handler:^(NSError *error) {
        if(error) {
        }
        OCMVerifyAll(delegate);
    }];
}

但是,我收到错误 failed: caught "NSUnknownKeyException", "[<__NSCFString 0x7faeaad6bd60> valueForUndefinedKey:]: this class is not key value coding-compliant for the key CompletedBy."

createChecklistItem 定义如下:

- (void)createChecklistItem:(id<IChecklistItem>)checklistItem delegate:(NSObject<ChecklistServiceDelegate> *)delegate
{
    NSMutableArray *mockChecklistItem = [NSMutableArray new];
    [TestObjectLoader loadObject:mockChecklistItem
                    fromJSONFile:@"ChecklistItem"
                     withMapping:[MappingProvider checklistCreateMapping]];
    if (delegate != nil && [delegate respondsToSelector:@selector (didCompleteCreateChecklistItem:)]) {
        [delegate didCompleteCreateChecklistItem:(NSObject<IChecklistItem> *)mockChecklistItem];
    }
}

其中 Checklist.json 是

{
    "Id": 13,
    "Desc": "Checklist Description",
    "IsCompleted": "false",
    "TypeId": 1,
    "RoleId": 1,
    "Status": "C",
    "CompletedDateTime": "2015-06-23T00:00:00+00:00",
    "CompletedBy": "AC",
    "Notes": [
              {
              "Note": "test",
              "CreatedBy": "AC",
              "CreatedDateTime": "2015-06-23T00:00:00+00:00"
              }
              ]
}

基本上,我想模拟服务,当调用 createChecklistItem 时,我只是想在对象上设置一个随机 ID 并将其传回,而不是通过 [= 的 ChecklistService 读取它34=] 文件。反正有这样做吗?我在我的测试中加入了模拟,但我不相信我使用正确...

您实际上不需要 Checklist.json,您应该只返回一个具有不同 ID 的值。

所以...

- (void)createChecklistItem:(id<IChecklistItem>)checklistItem delegate:(NSObject<ChecklistServiceDelegate> *)delegate
{
    NSMutableArray *mockChecklistItem = [NSMutableArray new];
    [TestObjectLoader loadObject:mockChecklistItem
                    fromJSONFile:@"ChecklistItem"
                     withMapping:[MappingProvider checklistCreateMapping]];
    if (delegate != nil && [delegate respondsToSelector:@selector (didCompleteCreateChecklistItem:)]) {
        [delegate didCompleteCreateChecklistItem:(NSObject<IChecklistItem> *)mockChecklistItem];
    }
}

应该只是

checklistItem.Id = 2; //Random number