0

I'm working with CoreBluetooth, so in my unit tests I'm mocking all the CB objects so they return what I want. In one of my tests, I mock a CBPeripheral, and stub the delegate method like so:

[[[mockPeripheral stub] andReturn:device] delegate];

The device passed in is my wrapper object which holds on to the peripheral. Later in the test, I call a method on device which then checks:

NSAssert(_peripheral.delegate == self, @"Empty device");

This line is being asserted during the test because _peripheral.delegate != self.

I've debugged through, and made sure that _peripheral is an OCMockObject. Why isn't the stubbed method returning device when the assert checks the _peripheral's delegate?

Here's the detailed code:

@interface Manager : NSObject
- (void)connectToDevice:(Device*)device;
@end

@implementation Foo

- (void)connectToDevice:(Device*)device {
    if([device checkDevice]) {
        /** Do Stuff */
    }
}

@end

@interface Device : NSObject {
    CBPeripheral _peripheral;
}
- (id)initWithPeripheral:(CBPeripheral*)peripheral;
@end

@implementation Device

- (id)initWithPeripheral:(CBPeripheral*)peripheral {
    self = [super init];
    if(self) {        
        _peripheral = peripheral;
        _peripheral.delegate = self;
    }
    return self;
}

- (BOOL)checkDevice {
    NSAssert(_peripheral.delegate == self, @"Empty device");
    return YES;
}

@end

@implementation Test

__block id peripheralMock;

beforeAll(^{
    peripheralMock = [OCMockObject mockForClass:[CBPeripheral class]];
});

//TEST METHOD
it(@"should connect", ^{
    Device *device = [[Device alloc] initWithPeripheral:peripheralMock];

    [[[peripheralMock stub] andReturn:device] delegate];

    [manager connectToDevice:device];
}
@end
Mark
  • 7,167
  • 4
  • 44
  • 68

1 Answers1

0

I am not able to reproduce this -- is this what you're doing?

@interface Bar : NSObject <CBPeripheralDelegate>
@property (nonatomic, strong) CBPeripheral *peripheral;
- (void)peripheralTest;
@end

- (void)peripheralTest
{
    NSAssert(_peripheral.delegate == self, @"Empty device");
}

// In test class:    
- (void)testPeripheral
{
    Bar *bar = [Bar new];
    id peripheralMock = [OCMockObject mockForClass:CBPeripheral.class];
    [[[peripheralMock stub] andReturn:bar] delegate];
    bar.peripheral = peripheralMock;
    [bar peripheralTest];
}

This test passes for me.

Ben Flynn
  • 18,524
  • 20
  • 97
  • 142
  • Pretty much, except there's an additional manger object in the process as well. I've updated the question with a more in depth code sample. – Mark Aug 30 '13 at 20:33
  • 1
    Ah, after some more careful debugging, it seems I was somehow running a second similar test before the original finished which used the shared mockPeripheral. After making the peripheral a local object, the tests passed. I'll accept your answer because it technically works for me now. – Mark Aug 30 '13 at 20:45