简体   繁体   English

分配给只读属性Objective-C

[英]Assigned to Readonly Property Objective-C

I am writing a unit test to test a method that updates a checklist. 我正在编写单元测试来测试更新清单的方法。 The checklist has these properties: 清单具有以下属性:

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;

- (void)sortNotes;
@end

However, in my unit test, as I am trying to validate, 但是,在我要验证的单元测试中,

checklistItem.Description = @"hello"; , I get the error"Assignment to readonly property" ,出现错误“分配给只读属性”

Why is this so? 为什么会这样呢?

heres the rest of my test method: 这是我测试方法的其余部分:

- (void)testUpdateChecklist {
    NSString *testChecklistId = @"1";
    NSString *testPatientDescription = @"Descriptive Description";

    // What other properties do I need here?
    XCTAssertNotNil(_service);
    __block CCChecklistItem *checklistItem = nil;

    SignalBlocker *blocker = [[SignalBlocker alloc] initWithExpectedSignalCount:1];
    id delegate = OCMProtocolMock(@protocol(ChecklistServiceDelegate));
    OCMExpect([delegate didCompleteUpdateChecklistItem:[OCMArg checkWithBlock:^BOOL(id obj) {
        checklistItem = obj;
        XCTAssertNotNil(checklistItem);
        [blocker signal];
        return true;
    }]]);

    [_service updateChecklistItem:checklistItem delegate:delegate];
    [blocker waitWithTimeout:5.0f];
    OCMVerifyAll(delegate);

    NSString *originalDescription = checklistItem.Description;

    checklistItem.Description = @"hello";

}

EDITED QUESTION: 编辑的问题:

So when I change the property from above to ReadWrite, I get this error in CChecklistItem 因此,当我从上方将属性更改为ReadWrite时,我在CChecklistItem中收到此错误

@interface CCChecklistItem ()
@property (nonatomic, assign, readwrite) NSInteger Id;
@property (nonatomic, copy, readwrite) NSString *Description;
@property (nonatomic, assign, readwrite) NSInteger RoleId;
@property (nonatomic, assign, readwrite) NSInteger GroupId;
@property (nonatomic, strong, readwrite) NSMutableArray<IChecklistNote> *Notes;
@end

`Illegal redeclaration of readwrite property in class extension 'CChecklistItem' `在类扩展名'CChecklistItem'中非法重新声明了readwrite属性

Your property is set to readonly as seen here: 您的媒体资源设置为readonly如下所示:

@property (nonatomic, copy, readonly) NSString *Description;

Change it to: 更改为:

@property (nonatomic, copy) NSString *Description;

or if you want to be consistent with the other properties (though overly explicit, IMO): 或者如果您想与其他属性保持一致(尽管过分明确,IMO):

@property (nonatomic, copy, readwrite) NSString *Description;

Changing scope visibility only to satisfy tests is not encouraged. 不鼓励仅为了满足测试而更改范围可见性。 The easiest solution in your case would be to take advantage of wonderful KVO which Objective-C gives you. 在您的情况下,最简单的解决方案是利用Objective-C为您提供的出色的KVO

Translated to your original question it would be something like: 转换为您的原始问题将类似于:

[checklistItem setValue:@"hello" forKey:@"Description"]

No need to change access modifiers and your tests will be fine. 无需更改访问修饰符,您的测试就可以了。

Your property is declared readonly in the protocol that the class CChecklistItem conforms. 在类CChecklistItem符合的协议中,您的属性被声明为readonly When that property is then synthersized it will create the backing variable and a getter method -(NSString *)description; 然后综合该属性时,它将创建后备变量和一个getter方法-(NSString *)description; but no setter method, since it is readonly . 但没有设置方法,因为它是readonly So redeclaring it as readwright in your anonymous category, that i'm guessing is declared in your test file to expose private methods to the test case, won't work since there still is no setter method for the property. 因此,在您的匿名类别readwright其重新声明为readwright ,以至于我猜测您的测试文件中将其声明为将私有方法暴露给测试用例,将无法正常工作,因为该属性仍然没有setter方法。 Further more, even if you decide to try to make your own setter in the implementation of a category on your class you can't since there is no way to access the variable _description that is only exposed in the CChecklistItem.m file. 此外,即使您决定尝试在类的实现中创建自己的设置器,您也无法做到,因为无法访问仅在CChecklistItem.m文件中公开的变量_description

Depending on what you need to do with your test it might work to stub the getter - (NSString *)description; 根据您需要执行的测试,对吸气剂进行stub可能有用- (NSString *)description; and return your @"hello" string when that method is called instead of trying to set the actual value to the backing variable. 并在调用该方法时返回@"hello"字符串,而不是尝试将实际值设置为backing变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM