0

我正在测试一种方法,该方法调用另一个迭代NSArray不同对象的方法,这些对象符合protocol <MNBNotificableTrabel>. 此方法检查是否每个对象isKindOfClass: oneClass或 otherClass 并返回一个给我。

    for (id <MNBNotificableTravel> travel in self.travelList) {
        if ([travel isGoodForNotification] && [travel notificationType] == MNBNotificableTravelTypeEditable) {
            if ([notificableTravel numberOfPoisOrAssetsForNotification] < [travel numberOfPoisOrAssetsForNotification]) {
                if ([travel isKindOfClass:[MNBNotificableTravelList class]] && !notificableTravel])) {
                    notificableTravel = travel;
                } else if ([travel isKindOfClass:[MNBNotificablePoiListDraft class]]) {
                    notificableTravel = travel;
                } 
            }
        }
    }
    return notificableTravel;
}

为了测试它,我创建了一个带有mockedObjects. 我用不同的方法创建了它们,而不是使用mockProtocol(),因为我想区分它们。

- (MNBNotificableTravelList *)fakeTravelListGoodForNotification:(BOOL)good numberOfPois:(NSUInteger)numberOfPois type:(MNBNotificableTravelType)type travelId:(NSString *)travelId {
    MNBNotificableTravelList * fakeTravel = mock([MNBNotificableTravelList class]);
    [given([fakeTravel isGoodForNotification]) willReturnBool:good];
    [given([fakeTravel notificationType]) willReturnInteger:type];
    [given([fakeTravel numberOfPoisOrAssetsForNotification]) willReturnInteger:numberOfPois];
    [given([fakeTravel travelID]) willReturn:travelId];
    return fakeTravel;
}

- (MNBNotificablePoiListDraft *)fakePoiListDraftGoodForNotification:(BOOL)good numberOfPois:(NSUInteger)numberOfPois type:(MNBNotificableTravelType)type travelId:(NSString *)travelId {
    MNBNotificablePoiListDraft * fakeTravel = mock([MNBNotificablePoiListDraft class]);
    [given([fakeTravel isGoodForNotification]) willReturnBool:good];
    [given([fakeTravel notificationType]) willReturnInteger:type];
    [given([fakeTravel numberOfPoisOrAssetsForNotification]) willReturnInteger:numberOfPois];
    [given([fakeTravel travelID]) willReturn:travelId];
    return fakeTravel;
}

- (void)testBuildLocalNotificationShouldCallScheduleMethodFourTimes {
    NSDate *installationDate = [NSDate date];
    [given([self.mockUserDefaults boolForKey:mnbUserHasAuthorizedLocation]) willReturnBool:YES];
    [given([self.mockUserDefaults objectForKey:mnbInstallationDateKey]) willReturn:installationDate];
    [given([self.mockDateGenerator notificationDatesForScheduleLifeCycleNotifications]) willReturn:[self fakeNotificationDatesWithInstallationDate:installationDate]];
    NSArray *fakeTravels = @[[self fakePoiListDraftGoodForNotification:YES numberOfPois:3 type:MNBNotificableTravelTypePublished travelId:@"1"],
                             [self fakePoiListDraftGoodForNotification:YES numberOfPois:3 type:MNBNotificableTravelTypeEditable travelId:@"3" ]];

    MNBLifeCycleNotificationBuilder *customSut = [[MNBLifeCycleNotificationBuilder alloc] initWithUserDefaults:self.mockUserDefaults application:self.mockApplication travelList:fakeTravels];
    [customSut buildLocalNotifications];
    [verifyCount(self.mockApplication, times(4)) scheduleLocalNotification:instanceOf([UILocalNotification class])];
}

当我对此进行迭代时,我的问题就出现了NSArray,如果我输入po travel输出是正确的并且我看到它是MNBNotificableTravelListor的模拟MNBNotificablePoiListDraft,但是如果我输入po [travel isKindOfClass:[MNBNotificableTravelList class]]输出总是nil.

我试图将响应添加到[isKindOfClass:]using given。但我认为这不是一个好方法,响应是一个十六进制数。

任何人都知道我怎么能正确测试这个。

谢谢

4

1 回答 1

0

解决方案 1:不要在代码中使用 isKindOfClass。内省很酷,但避免使用它几乎总是一种更好的做法。所有条目都符合的协议上的方法可用于合并逻辑,或使用控制反转之类的模式:http ://en.wikipedia.org/wiki/Inversion_of_control可以帮助您避免询问对象它们是什么类型并以此为基础进行切换。

解决方案 2:模拟/覆盖 isKindOfClass: 应该没问题。这些是模拟对象,它们应该以非标准方式表现。查看isKindOfClass和 isMemberOfClass: 的 NSObject 文档,并在您的模拟对象中覆盖它们。

于 2015-03-16T16:21:00.553 回答