Best practices for testing dispatch_once

35 views
Skip to first unread message

Jason McKee

unread,
Nov 30, 2015, 6:57:40 PM11/30/15
to Cedar Discussion
I find myself in a somewhat unique situation.  I'm using SDWebImage to make requests that utilize the Cloudinary Image Transformation API.  Since the quantity of images is low I'm having the SDWebImagePrefetcher initiate the prefetching of all images as soon as the final size of the imageview in my tableviewcell is known (which as far as I can tell is tableView:willDisplayCell:forRowAtIndexPath:).  Since that method is called very frequently, I put the prefetch call in a dispatch_once() block.  In the dispatch_once template, and most implementations I've seen, the token is declared statically right before the dispatch_once.  Given that this view controller is my initial view controller and I'm running as a test bundle, this token is spent before any of my specs run.  To combat this, I have declared it outside the @implementation block in the .m file.  In spec I can extern the token and reset it before invoking the tableView:willDisplayCell:forRowAtIndexPath:

This solution makes it testable, but feels "yucky".  Is there a well established pattern around testing these types of situations?  I realize this situation is oddly specific, but I suspect there may be a generally better way to handle these tokens.

Thanks,
-Jason

Brian Croom

unread,
Dec 18, 2015, 2:05:23 PM12/18/15
to cedar-...@googlegroups.com
Hi Jason!

I'm sorry for not getting back to you sooner. I would personally take a bit of a different approach to solving that particular problem in order to avoid dispatch_once altogether. I would suggest:
  1. Create a new Prefetcher class that encapsulates access to the SDWebImagePrefetcher. I would give it a method for kicking off the prefetching process which takes the size information as a parameter. This class would internally maintain state to keep track of whether prefetching has already begun, and only do it once for a given size.
  2. Inject a prefetcher instance into your view controller, making sure the same instance is used each time.
  3. Call the prefetcher method once you have gathered the size data you need
This will make the view controller test very straightforward, and the prefetcher should be pretty easily testable as well. The key insight here may be that there is no need to keep truly global state (the dispatch token) because it can actually be scoped more tightly.

What do you think?

--Brian

--
You received this message because you are subscribed to the Google Groups "Cedar Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cedar-discus...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Brian Croom
Agile Engineer
Pivotal Labs, Toronto
Reply all
Reply to author
Forward
0 new messages