0

I have a piece of code, which is processing a queue synchronously and asynchronously. I'm using OCMock to test the thing and individually I can test both cases (synchronous and asynchronous) but when I test for both at the same time I get trouble.

To verify that the queue is processed correctly I'm passing it a mocked listener and from this listener I'm then asking if it got all the notifications propagated by the queue processor. I have two tests and in the first test (asynchronous) these expectations are met but with the second test (synchronous) I get this error:

OCMockObject[JHQueueListener] : 4 expected methods were not invoked: 
        startedProcessingQueue
        startedToProcessQueueItem:OCMockObject[JHQueueItem]
        finishedProcessingQueueItem:OCMockObject[JHQueueItem]
        finishedProcessingQueue

Here's a link to the project: https://github.com/jphollanti/queue-processor

And here's a link to the test: https://github.com/jphollanti/queue-processor/blob/master/QueueProcessorTests/JHQueueProcessorTests.m

JHollanti
  • 2,343
  • 8
  • 27
  • 39
  • Are you sure that the queue processor starts executing before you check to see whether it's executing or not? In this case, you'd fall out of your inProcess check because you were not yet processing, and then OCMock would correctly tell you that nothing happened before you finished. – gaige Mar 27 '13 at 20:44
  • Thanks for the suggestion. That wasn't the case but i did manage to move ahead with the problem. It turns out i had to check for ([NSThread isMainThread]) and then send the notifications a bit differently if it's already in the main thread. But what's weird still is that it's now somehow randomly failing... Weird. – JHollanti Mar 27 '13 at 21:05

1 Answers1

0

Issue #1: The references are fine but when it comes to the tests, threading is expected to work incorrectly. The problem here is that a new thread is started and in that new thread the status of the queue is set as in progress. But it takes longer to start up a new thread than it does for the main thread to ask for the status and this results in the fact that the queue is not (yet) in progress. Adding a delay of some 10000ms should help things a lot. Like so:

...
  [queue processQueueAsynchronously:queueItems];

  usleep(10000);

  BOOL wentToThread = NO;
  while ([queue isInProgress]) {
    wentToThread = YES;
    ...
  }
...

Also, calling dispatch_async(dispatch_queue_t queue, ^(void)block) takes a lot of time and this adds up to the "random" nature of the issues.

Issue #2: Calling dispatch_async(dispatch_get_main_queue(), ^{ ... } from the main thread causes the block to be sent to some queue which is executed at some time (don't know how it works). This is why the second test (synchronous) failed. Using something like this helps:

if ([NSThread isMainThread]) {
  for (id <JHQueueListener> listener in listeners) {
    [listener startedToProcessQueueItem:queueItem];
  }
} else {
  dispatch_async(dispatch_get_main_queue(), ^{
    for (id <JHQueueListener> listener in listeners) {
      [listener startedToProcessQueueItem:queueItem];
    }
  });
}
JHollanti
  • 2,343
  • 8
  • 27
  • 39