简体   繁体   中英

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

@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'

Your property is set to readonly as seen here:

@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):

@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.

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. When that property is then synthersized it will create the backing variable and a getter method -(NSString *)description; but no setter method, since it is 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. 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.

Depending on what you need to do with your test it might work to stub the getter - (NSString *)description; and return your @"hello" string when that method is called instead of trying to set the actual value to the backing variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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