Unit test: what to test and how to do it in iOS?

Kent Winder
Nextzy
Published in
4 min readMay 23, 2017

You heard a lot about people talking about test coverage must be as high as possible, right? (Except for those who say it’s a waste of time) So, how high should it be? 100%? Yes, that the ideal number, we should write test for everything. But, this number can be misleading sometimes, because every line of code that is called during tests are considered covered, and a line of code can also be called without being tested. Besides, this is not an ideal world, and you can call me simple minded but I’m not that kind of guy. Why? Because knowing what you should test will save you a lot of time writing bunch of funtions to test something you can run the app and see the result right away. And writing test usually requires breaking down your code, therefore more useless tests result in less readable code.

So, when to write test?

  • When it's not ready
    You have to call a web service but the api is not built yet, or you have to interact with other part of the project but the other guy in your team hasn't finished it. So, you can write your code, then write unit tests to confirm that it does what you would expect it to do.
  • When it is time related
    Let's say your app has to back up data at the end of every day, you cannot wait until then to test whether it will work or not, right? Sure you can change date and time settings in the system, it's faster but still time consuming and not very effective.
  • When it is really hard to trigger manually
    In game, for example, user will get an archievement after completing some quests. Try comparing testing by playing game with writing code to confirm that the award gets triggered when the condition is hit.
  • Others than these, you should consider writing tests when refactoring code to make sure you are not breaking something, when fixing a bug so a fixed bug stay fixed, for classes which are too complex.

Callbacks vs delegates

I myself prefer callbacks over delegates for methods when coding, why is that? We can discuss it in another article, but in testing, they have their own advantages and drawbacks.

  • Callbacks work well in asynchronous functions, you don’t have to mock every protocol with some booleans to keep track of which functions get called, you just test if callbacks get called or they are called with the right result.
  • Delegates are suitable for external classes, when your object under test calls another class, you have to mock that class, and delegates make it easier

When to mock?

If your method is calling a different class, it means you have dependency here, then use mocks to test. They are very useful for testing interactions between your object and a particular interface. If you test that code path with the actual dependency, you are not unit testing, you are integration testing, so, instead of passing a real object, you can pass a mock implementation of that interface and set expectations on calls to the dependent object, set the values it should return to you to perform the test you want, or what exceptions to throw, so you can test your exception handling code.

Note: a good mock should be quick and easy to write, relatively short and does not contain much information you don’t need, and you must have a legitimate reason to not use the real object.

Singleton

Singleton pattern is evil for testing when you use it the wrong way, instead of using it to make sure one and only one instance of a given class exists during runtime, we use it as a global state. Why is this bad? Let’s say we have a singleton class like this one:

And most of us usually use this class somewhere like this:

The problem with this one is we can’t access the sharedInstance to know if doSomethingAwesome has been called. For someAwesomeValue, if we have several tests, the state of the previous test can easily mess up your current test, it’s really hard to verify its value was set as expected. So, testing singleton for this one only works when you run it as part of the suite. To make this testable, singleton can be obtained via dependency injection.

Demo

I have written a small demo for this article, it’s an application that get and display current weather details for a specific city. There is one service to retrieve the weather details, one view controller to display the details. We will write tests for these classes.

Demo application can be downloaded at: https://github.com/kentwinder/UnitTest-Demo

I hope you learn something from this article

--

--

Kent Winder
Nextzy
Editor for

Just a regular guy who loves coding, reading, and getting tattoos