Question

I have a following method :

+(Group*)groupWithID:(NSString *)idNumber
           inContext:(NSManagedObjectContext *)context
{
    Group *group = nil;
    if(idNumber && context)
    {
        NSArray *result = [Group MR_findByAttribute:@"idNumber" withValue:idNumber inContext:context];
        if(!result || result.count > 1)
        {
            // TODO (Robert): Handle error for more than one group objects or error nil results
        }
        else if(result.count == 0)
        {
            group = [Group MR_createInContext:context];
            group.idNumber = idNumber;
            NSAssert(group != nil, @"Group should not be nil!");
        }
        else
        {
            group = [result lastObject];
        }
    }

    return group;
}

I am testing it with a following kiwi spec :

it(@"should create new object with new id", ^{
    [[[Group class] should] receive:@selector(MR_createInContext:)];
    Group *group = [Group groupWithID:@"12345"
                            inContext:[NSManagedObjectContext MR_contextForCurrentThread]];
    [[group should] beNonNil];
    [[[group idNumber] should] equal:@"12345"];
});

With a following setup :

beforeEach(^{
        [MagicalRecord setupCoreDataStackWithInMemoryStore];
        [MagicalRecord setDefaultModelNamed:@"Model.mom"];
    });

    afterEach(^{
        [MagicalRecord cleanUp];
    });

The problem is that method MR_createInContext returns a nil, and I do not know what could be the reason as in some other tests that same code produces a valid non-nil object.

Was it helpful?

Solution

As you've discovered, when you set a receive expectation, Kiwi stubs that method on the object, regardless of whether it's a regular object, a Class object, or an actual Kiwi mock / test double (https://github.com/allending/Kiwi/wiki/Expectations#expectations-interactions-and-messages).

If what you're trying to test is that your +groupWithID:inContext: helper behaves correctly, you don't actually want the real implementation of MR_createInContext:. A "should receive" expectation is designed to test that you're sending the right message, but to avoid executing the real code.

Maybe something like this:

it(@"creates a new group if one does not exist with the specified id", ^{
    // stub MR_findByAttribute to return no results
    [Group stub:@selector(MR_findByAttribute:withValue:inContext:) andReturn:@[]];

    // stub MR_createInContext to use our test group so that we can set
    // expectations on it
    id context = [NSManagedObject MR_defaultContext];
    id group = [Group MR_createInContext:context];
    [[Group should] receive:@selector(MR_createInContext:) andReturn:group withArguments:context];

    // call the method we want to test
    [Group groupWithID:@"1234" inContext:context];

    // test that the id was set correctly
    [[group.idNumber should] equal:@"1234"];
});

OTHER TIPS

Well, as usual 5 seconds after I give up and go to stack overflow, I found the answer. Well initially my interpretation of

[[[object should] receive:@selector(selector_name:)];

was that the original object is not affected it any way, and that kiwi somehow knows that this object should receive this selector. Turns out that if I test, whether object receives selector, this object gets replaced with a mock or method is swizzled therefore the normal functionality is gone. This is the reason why i was getting a nil.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top