iosobjective-ckiwi

How to stub readonly property with Kiwi 2, Objective-C


looking for little help on accessing readonly property with Kiwi. In short, I want to test if _myReadOnlyDict gets initialized or not. Problem is that myReadOnlyDict is still always empty(has no contents), despite that in beforeEach block it is mocked and a value added to it.

    // All these return 0
    ad.myReadOnlyDict.count;
    [[ad myReadOnlyDict] allKeys].count;
    [ad myReadOnlyDict].count;

What I am missing here?

Any help is appreciated!

Please see the code below:

In AppDelegate.h I have a porperty.

@property (nonatomic, readonly) NSDictionary * myReadOnlyDict;

In AppDelegate.m I have a method, which is called from AppDelegate's didFinishLaunchingWithOptions method.

- (void)initConfig
{
    _myReadOnlyDict = [NSJSONSerialization JSONObjectWithData:[self jsonData] options:nil error:nil];
}

I have a Kiwi test set up

describe(@"App Delegate", ^{

    __block AppDelegate *ad;

    beforeEach(^{
        ad = [[AppDelegate alloc] init];

        NSMutableDictionary * mockedDict = [NSJSONSerialization nullMock];

        mockedDict[@"my_data"] = @"my_value";

        [ad stub:@selector(myReadOnlyDict) andReturn:mockedDict];
    });

    afterEach(^{
        ad = nil;
    });

    context(@"when smth happens", ^{
        it(@"should do smth else", ^{
            [[ad should] receive:@selector(initConfig)];

            // These three lines fail
            [[theValue([ad myReadOnlyDict].count) shouldNot] equal:theValue(0)];
            [[theValue(ad.myReadOnlyDict.count) shouldNot] equal:theValue(0)];
            [[theValue([[ad myReadOnlyDict] allKeys].count) shouldNot] equal:theValue(0)];

            [ad initConfig];
        });
    });
});

Solution

  • Your problem is caused by the fact that [NSJSONSerialization nullMock]returns a null mock, which is an object that does nothing for any called method, and returns nil/0 to any method that must return something.

    This should work:

    NSMutableDictionary * mockedDict = [@{@"my_data": @"my_value"} mutableCopy];
    [ad stub:@selector(myReadOnlyDict) andReturn:mockedDict];