0

So I am attempting to throw together a simple test to verify that I am receiving frequency values from my audioController correctly.

In my view I am making a call like this to setup up a block callback:

- (void) registerVolumeCallback {
      NSNumberBlock frequencyCallback = ^(NSNumber *frequency) {
          self.currentFrequency = frequency;
      };
      self.audioController.frequencyCallback = frequencyCallback;
  }

In my audio controller the frequency callback block is called with an nsnumber containing the frequency.

In my tests file I have the following:

    - (void) testFrequencyAudioServiceCallbackActive {
          OCMockObject *mockEqualizer = [OCMockObject partialMockForObject:self.testEqualizer];
          [[[mockEqualizer stub] andCall:@selector(mockDidUpdateFrequency:)
                      onObject:self] setCurrentFrequency:[OCMArg any]];
          [self.testEqualizer startAnimating];
          [ mockEqualizer verify];
    }

And:

   - (void) mockDidUpdateFrequency: (NSNumber *) frequency {
        GHAssertTrue((frequency!= nil), @"Audio Service is messing up");
  }

Where test equalizer is an an instance of the aforementioned view. So Im trying to do some swizzling here. Problem is, mockDidUpdateFrequency is never called. I tried putting:

 self.currentFrequency = frequency;

outside of the block, and the swizzling does happen and I do get a call to mockDidUpdateFrequency. I also tried:

 - (void) registerVolumeCallback {
     __block UIEqualizer *blockSafeSelf = self;
     NSNumberBlock frequencyCallback = ^(NSNumber *frequency) {
       blockSafeSelf.currentFrequency = frequency;
     };
    self.audioController.frequency = frequencyCallback;
}

No luck. Some weird instance stuff is going on here in the block context that I am not aware of. Anyone know whats happening?

Greg Price
  • 2,556
  • 1
  • 24
  • 33

1 Answers1

0

You'll need to provide some more details for a definitive answer. For example, how is registerVolumeCallback invoked? And is frequencyCallback your own code, or a third-party API?

With what you've provided, I suspect that frequencyCallback is an asynchronous call. So even though startAnimating might create the condition where it will eventually be invoked, you immediately verify the mock before the callback has had a chance to be invoked. To get your test to do what you want as written, you need to understand what queue that block is executed on, and you need to give it a chance to execute.

If it's invoked asynchronously on the main queue, you can let the main run loop spin before calling verify:

[self.testEqualizer startAnimating];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.1]];
[mockEqualizer verify];

If it's invoked on a different queue, you have some different options, but it would help to have a clearer picture how your code is structured first.

Christopher Pickslay
  • 17,523
  • 6
  • 79
  • 92