Advanced iOS Series — Episode II: Best Way to Write Unit Tests to Network Requests

Enes Buğra Yenidünya
4 min readAug 31, 2022

If the iOS application you have developed has Network Requests (Innately internet connection), this will be one of the first modules you should consider when writing a unit test.

Of course, we have other points to think about. How do we best write unit tests for our network requests? As you know, there are several approaches. Mocking, Stubbing and Faking are some of the examples.

In this article, we will discuss why we should choose which approach and make the mentioned improvements step by step, accompanied by a sample project.

You can find the sample projects source code here.

Table of Contents

1-) Entry level of writing unit tests for network requests

2-) What is a URLProtocol?

3-) What is the best way of writing unit tests to network requests?

4-) Creating a MockURLProtocol

5-) Writing Unit Test using MockURLProtocol

6-) Conclusion

Entry level of writing unit tests for network requests

We can create a Mock class of our NetworkClient class that manages network calls. This MockNetworkClient would be inherited from NetworkClient and has all its capabilities of it. This would give us changes to test some of its logic e.g. count of network calls and whether we call the correct function or not...

Maybe you have thought about why this is an entry-level way of writing unit tests for network requests. Did you consider the critical point of network request testing? Let me tell you for you, not calling the actual network request function. We do not want to make a real network request and this entry-level way is not providing us to make it possible.

What is a URLProtocol?

Apple provides us with a class called URLProtocol. Its name contains the word ‘Protocol’ but it’s actually a class. They are describing the URLProtocol as shown above:

An abstract class that handles the loading of protocol-specific URL data.

What is the best way of writing unit tests to network requests?

Sake of the best way we need to create MockURLProtocol inherited from URLProtocol and override its methods. We will use this MockURLProtocol inside a MockURLSession and we can inject it anywhere we want to test.

Benefits of the MockURLProtocol

  • Preventing from making real network calls
  • Full control of network request responses
  • Compatible with any 3rd party network libraries and managers

I think these benefits are enough for putting our unit tests in the category of “Best Way”.

Moreover, if you don’t own the class don’t inherit it directly. Unexpected behaviors can occur and you will probably inherit a bunch of logic you don’t need.

Creating a MockURLProtocol

Now its time to create a Mock version of URLProtocol class. See below screen shot for implementation details.

MockURLProtocol Class

As you can see we are overriding a couple of methods from our super class URLProtocol.

We are overriding canonicalRequest, startLoading and stopLoading methods because they are required. We have two canInit functions that take two different arguments URLRequest and URLSessionTask. Simply returning true inside them for allowing our MockURLProtocol to be used by URLSession.

The crucial point is inside the startLoading function. We are checking if our handler is returning success or error, then telling the client that the process is completed with one of the options.

Writing Unit Test using MockURLProtocol

As a result of all these examinations and developments, it finally came to write the Unit Test we were aiming for.

If you don’t have any idea about writing Unit Tests and TDD (Test Driven Development), check out my medium article about this topic from here.

I won’t deep dive about the code but let me share the idea in here and see how we are using MockURLProtocol with URLSession.

Example Unit Test Method
Helper Methods

Helper methods are showing all the idea behind this implementation. makeSUT method is used for injecting our MockURLProtocol to actual NetworkManager and creating our UserAPI. Our test method is using this UserAPI.

injectMockData function is used for creating mock response with given User model. Notice how we are stubbing requestHandler.

Conclusion

Testing network requests sounds easy and yes it's not that hard. Since we are Senior iOS Developers and want to write better code that covers all the scenarios, reusable, loosely-coupled and modular, we should consider the best ways of it.

Mocking URLProtocol gives us great benefits and when we compare it with the entry-level approach it’s more accurate.

--

--

Enes Buğra Yenidünya

iOS Engineer — Freelancer #iOS #swift #mobileappdevelopment #software #apple