Question

Is there any way to ensure that a class posts a particular NSNotification?

(I have a set of classes, and I would like to enforce at compile-time (if possible) that the class posts a required NSNotification).

Alternatively, if that is not possible, is there any workaround?

Was it helpful?

Solution

It's fundamentally impossible to predict at compile time what will happen at run time. The closest you can get is static analysis, but even that can't predict anything that happens outside of your own code, such as inside Foundation.

You can, however, do this with unit tests, since the test runner actually runs the code under test.

You'll need to create a test bundle target, if you haven't already. Your target will use SenTestingKit to run your tests, which you create. (On the iPhone, you'll also need Google Toolbox for, uh, Mac. They have a handy tutorial on using GTM for iPhone tests.)

You'll create a SenTestCase subclass to test whether your real object posts a notification. It'll look something like this:

@interface FrobnitzerNotificationsTest: SenTestCase
{
    BOOL frobnitzerDidCalibrate;
}

- (void) frobnitzerDidCalibrate:(NSNotification *)notification;

@end

@implementation FrobnitzerNotificationsTest

- (void) testFrobnitzerCalibratePostsNotification {
    Frobnitzer *frobnitzer = …;
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

    [nc addObserver:self
        selector:@selector(frobnitzerDidCalibrate:)
        name:FrobnitzerDidCalibrate
        object:frobnitzer];

    frobnitzerDidCalibrate = NO;

    //This should post a notification named FrobnitzerDidCalibrate with the receiver as the object.
    [frobnitzer calibrate];
    //If it did, our notification handler set frobnitzerDidCalibrate to YES (see below).

    [nc removeObserver:self
        name:FrobnitzerDidCalibrate
        object:frobnitzer];

    STAssertTrue(frobnitzerDidCalibrate, @"Frobnitzer did not post a notification when we told it to calibrate");
}

- (void) frobnitzerDidCalibrate:(NSNotification *)notification {
    frobnitzerDidCalibrate = YES;
}

@end

You'll need one instance variable and one notification-handler method for every notification you want to test for, and one test method for every method you want to test for notifications.

Also, if using GTM, you must substitute GTMSenTestCase for SenTestCase above.

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