Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Test-Driven iOS Development with Swift  - Fourth Edition

You're reading from  Test-Driven iOS Development with Swift - Fourth Edition

Product type Book
Published in Apr 2022
Publisher Packt
ISBN-13 9781803232485
Pages 280 pages
Edition 4th Edition
Languages
Author (1):
Dr. Dominik Hauser Dr. Dominik Hauser
Profile icon Dr. Dominik Hauser

Table of Contents (17) Chapters

Preface 1. Section 1 –The Basics of Test-Driven iOS Development
2. Chapter 1: Your First Unit Tests 3. Chapter 2: Understanding Test-Driven Development 4. Chapter 3: Test-Driven Development in Xcode 5. Section 2 –The Data Model
6. Chapter 4: The App We Are Going to Build 7. Chapter 5: Building a Structure for ToDo Items 8. Chapter 6: Testing, Loading, and Saving Data 9. Section 3 –Views and View Controllers
10. Chapter 7: Building a Table View Controller for the To-Do Items 11. Chapter 8: Building a Simple Detail View 12. Chapter 9: Test-Driven Input View in SwiftUI 13. Section 4 –Networking and Navigation
14. Chapter 10: Testing Networking Code 15. Chapter 11: Easy Navigation with Coordinators 16. Other Books You May Enjoy

Chapter 10: Testing Networking Code

Almost all iOS apps communicate with some kind of server to synchronize data to other devices or to provide additional features that are not possible on the iOS device alone. As the code of the server application is separate from the code of the iOS application, the unit tests for the iOS app should not test features implemented in the server application. The unit tests for the iOS app should only fail if the code of the iOS app has bugs.

To achieve that, the unit tests need to be independent of the server application. This separation has several advantages. The main ones are as follows:

  • The unit tests are faster when they don't need to wait for the responses of the server.
  • The unit tests do not fail because the server is not available.
  • The networking code can be developed using test-driven development, even before the server application is available.

In this chapter, we will implement two different kinds of networking...

Mocking CLGeoCoder

CLGeoCoder is a class provided by Apple that helps you to get coordinates from an address string and vice versa. The methods in CLGeoCoder are based on completion closures. In this chapter, we will explore how to mock and test such methods.

Cleaning your project

Before we write the first test for this chapter, let's clean up the project a bit. Add sections in the project navigator and move the files to those sections according to your structure scheme. For inspiration, here is the structure I use for the main target:

Figure 10.1 – Adding structure in the project navigator

Your structure can be completely different. Use the structure you usually use in iOS projects. Also, add a similar structure to the files in the test target.

When you add new files to the project, you have to choose the correct folder depending on the structure you applied.

Preparations for the tests

Before we can write tests for the APIClient...

Testing async/await code that communicates with URLSession

In 2021, Apple introduced async/await in Swift. With async/await, asynchronous code (for example, fetching information from a server) is easier to write and easier to understand. In this section, we will learn how to implement fetching data from a web server using the async/await APIs of the URLSession class; and we will do this, of course, using test-driven development.

Unit tests need to be fast and repeatable. This means we don't want to rely on a connection to a real server in our unit tests. Instead, we will replace the communication with the server with a mock object.

Follow these steps to implement fetching to-do items from a server:

  1. In the test, we will use a mock object of a URLSession class instead of the real URLSession instance. To be able to replace the real URLSession instance with the mock, we need a protocol that defines the interface we want to replace.
  2. Add the following protocol definition...

Handling errors

To test the handling of errors in the URLSession call to the web service, we first need to enhance URLSessionProtocolMock. Follow these steps to test that an error in fetching data is passed down to the caller of the APIClient instance:

  1. Add the following property to URLSessionProtocolMock:
    // URLSessionProtocolMock.swift
    var dataForDelegateError: Error?
  2. Next, add the following handling of the error to the start of data(for:delegate:):
    // URLSessionProtocolMock.swift
    if let error = dataForDelegateError {
      throw error
    }

If there is an error set to the dataForDelegateError property, we throw it before we do anything else in this method.

  1. Now, we are ready to add the test method to APIClientTests:
    // APIClientTests.swift
    func test_toDoItems_whenError_shouldPassError() async
     throws {
      let urlSessionMock = URLSessionProtocolMock()
      let expected = NSError(domain: "", code: 1234)
      urlSessionMock.dataForDelegateError...

Summary

In this chapter, we have learned how to write tests for calls to CLGeoCoder and how to test the async/await REST API calls of URLSession. We have seen what we need to do in the test method to test whether an error is thrown in an async/await call. In addition, we have learned how to make our network code tests independent from the implementation of server infrastructure. This way we made our tests fast and robust.

You can use the skills gained in this chapter to write tests for the complete network layer of your apps. But you don't have to stop there. The strategies we've covered in this chapter also help to write tests for all kinds of async/await APIs.

In the next chapter, we will put all the code that we wrote up to now together, and finally see the app running on the simulator.

Exercises

  1. We have deactivated a test method using the x_ prefix to hide it from the test runner. There are other ways to deactivate a single test. Do some research on the internet to figure these out.
  2. In this chapter, we wrote tests for the async/await API of URLSession. But, URLSession also provides an API that uses the delegate pattern and one that uses Combine. Do some research on the internet to find out how to write unit tests for these APIs. Make sure that these tests also run when there is no connection to the server.
lock icon The rest of the chapter is locked
You have been reading a chapter from
Test-Driven iOS Development with Swift - Fourth Edition
Published in: Apr 2022 Publisher: Packt ISBN-13: 9781803232485
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}