Decode JSON with Swift (& test!)

Download, decode and test? O.K. then

Image for post
Image for post
Photo by Pankaj Patel on Unsplash

It is almost without exception essential that for any application (of a decent size) that you communicate with a backend server. This might be to get pertinent information, upload analytics information or any one of a host of reasons to communicate with another machine.

This article is about taking JSON and decoding it in an App.

Difficulty: Beginner | Easy | Normal | Challenging

Prerequisites:

Terminology

API: Application programming interface. A set of accessible tools for building software applications

Backend: the part of a computer system or application that is not directly accessed by the user, typically responsible for storing and manipulating data

Endpoint: An endpoint is a remote computing device that communicates back and forth with a network to which it is connected

JSON: JavaScript Object Notation, a lightweight format for storing and transporting data

Unit testing: Software testing where individual units or components of the software is Software testing where individual units or components of the software is tests

Swift Networking Terminology

URLSession: The class and related classes proved an API for downloading data to and from endpoints indicated by URLs

The setup

This is rather similar to mocking URLSession and making use of dependency injection to do so, and the purpose of this article is to discuss how we can take a resultant JSON String and actually test the response.

The model

The URL that is hit is the https://jsonplaceholder.typicode.com and the example Endpoint. Looking at that website, we expect the following response from the server in the form of a JSON string.

Image for post
Image for post

Our Codable class as represented below will give us an object model for the JSON input.

Calling the URL

We can actually make the call through a nicely written function like the following;

Testing the URL Call

We then can test this function, making sure we have our mock and have armed it with appropriate data (within the test)

The three quotation marks “”” produce multi-line String literals, and therefore can be used (given a little luck) to test that the response from the URLSessionMock() is truly the date we give it (spoiler: It is!)

The test can look something like the following:

Which makes everything seem great. But we aren’t testing the (you know) JSON String decoding.

Setting up the String Decoder

Option 1: Untestable

You could just call testdownload from viewDidLoad() (or a button press action), like the following:

This, of course works. But it prints the result to the console, and that isn’t really testable is it (Sir)?

Option 2: Extract out the decoder

So the idea here is to create a decoder function.

To make this reusable I’ll use some generics (but don’t be scared!) The following can be called through a little bit of fun with a do try catch. We tell the function that it will use UserModel.self to decode the data called success.

which then calls the following function:

Testing the JSON String decoding

Now in order to check that we have make sure that UserModel conforms to the Equatable protocol

Then we can set up a test that actually tests this (again using the data String from above)

I advise all reading this article to go to the Repo and download the files to have a read through.

In truth, the trickiest part of this is testing, and of course relies on your understanding of mocking. Good luck!

Conclusion:

Look, OK you’ve got me. I’ve used my own HTTPManager class in my own projects and I use that to decode my JSON from Endpoints.

However this particular article really breaks down how you can decode JSON, and even test the response (and believe me, you’ll want to test responses without hitting your Endpoint every time; your backend guy might periodically take it down and then….)

Extend your knowledge

  • If you want to create your own fake endpoint there are a few solutions, but I recommend jsonplaceholder, which you can use in your on test projects. the repo is through this link HERE
  • In a real implementation I’d use my HTTPManager class for these types of operations

The Twitter contact:

Any questions? You can get in touch with me HERE

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