A Complete guide to Unit Testing in Swift- Part II

Photo by Émile Perron on Unsplash

Part I: https://medium.com/@nishan/a-complete-guide-to-unit-testing-in-swift-part-i-4dd4c37926dd

In the first part, we covered the basics of Unit Testing. We created a basic calculator and wrote test cases for its functionality. In this part we will dive more into a real world scenario.

Unit Testing & Testable Code

Another terminology that is synonymous with Unit Testing is writing Testable Code.

Your code can be clear, understandable and self-documented but still untestable at the same time.

So what does writing testable code means? While writing tests, we prefer our code to be an isolated unit. One that takes an input & provides an output. One that follows SOLID, DRY or KISS principles. If our code performs lots of unrelated operations, then the complexity of writing tests increases.

One example of this in iOS is the misuse of UIViewController.

Untestable ViewController

Above UIViewController is responsible for fetching some data from api, process the logic behind setting the label and then finally set the label with the data. In this case, if you want to write a unit test for testing the condition to update the label, it becomes impossible.

In an ideal scenario, View Controller should be concerned only about operations related to view, not about business logics such as fetching data from api or conditions to update the label.

Writing Testable Code

So how can we make it testable? Let’s refactor our code first.

Refactored Code

We moved business logic to its separate class LabelDataService” which conforms to DataService protocol. We could have moved the logic to fetch data from api to another class but for the sake of simplicity, lets work with above code. Here we can easily test the condition to update the label in a similar way that we did to test calculator functionality.

Unit Tests for Refactored Code

But what if you want to write unit tests for “fetchDataFromApi()” method? Implementing a test case where you fetch data from a real api everytime your test runs might not be feasible scenario. There might be numerous api related operations in your project and running tests for them would take a long time to complete. Also tests might fail or pass depending upon the server or network conditions. So in real life, to simulate these type of scenario we use Mocks”.

Mocks

Simply put, Mocks are the fake implementation of your real code. Lets see an example where we mock “fetchDataFromApi()” method.

Mock for LabelDataService class

We replaced the real implementation of “fetchDataFromApi” with a fake one which returns either success or error. Initializer for this mock requires a boolean value to determine whether to simulate success or error condition.

Now we can easily write test cases which doesnot depends upon the network request.

Lets recall what we did. We refactored our code to make it testable, created a mocks to simulate api request and learned about writing unit tests using that mocks.

In the next and final part, we are going to learn how to write unit tests for asynchronous code, delegates & closures.

Part III: https://medium.com/@nishan/a-complete-guide-to-unit-testing-in-swift-part-iii-cdebcb5d1904

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Nishan

Nishan

Code, Eat, Sleep, Travel, Repeat