iOS TDD: Testing a method that uses UIVIew animateWithDuration:animations:completion:

ios, iphone, objective-c, tdd

Solution

I would simply make a property that determines the length of the animation and have it default to 0.5 seconds.

That way, your test can set the animation duration to 0 and observe that the label's text is updated without waiting.

This is dependency injection, and it's wildly useful if you just starting with TDD. It also has the nice side-effect of make your code more modular and less coupled.

Problem

I have a button press that fires off an animation, and upon completion of the animation, changes the text of a label. I'd like to write a test verifies that when the button gets pressed, eventually the text of the label changes properly. The implementation of the button press IBAction will use `[UIView animateWithDuration:animations:completion:]`. I obviously don't want my unit test to actually wait 0.5 seconds for an animation to complete. I thought about mocking UIView, but it seems odd to inject UIView as a dependency to a view controller. Further, the mocking framework I'm using (OCMockito) doesn't seem to work well with mocking class methods. I also thought about method swizzling or writing a testing category for `UIView`, and using an implementation that does nothing but invoke the `animations:` block followed by the `completion:` block. That seems a bit broken to me; I worry that overriding the implementation of a class method on UIView may have unintended consequences down the road. Being new to TDD, I'm not sure what best practice is here. Is this one of those pieces of code that should be considered "UI twiddling" and therefore it's acceptable to leave untested? Or is there some more obvious way to test this that I am missing?

Original source