Testing your backend integration with ease
Different ways for mocking yout data
While working on a client application, you may be wondering, what is the most effective way to test (or even to develop) your networking layer without trying to alter the backend in order to replicate certain scenarios.
Working with the backend is time consuming. Real requests take time, you may have to follow certain steps for every action you are trying to test and in many cases, you may not even have the flexibility to reproduce certain states in your backed.
So what can you do to make your life easier? Let’s have a look at some of the options, here is a breakdown of what will we look at:
- Mocking your data
- Mocking your network layer
- Setting up a local dev server manually
- Using a mock server application
Note, that while the code in this article is written for iOS, the core principles are universal and can be applicable to most programming languages and environments
Mocking your data
One of the easiest options is to mock your data. The way you do this is highly dependent on you application’s code, but generally you would want your data provider to be easily swappable. This way, while developing (or in your automated tests) you can replace it with something that returns mock data instead of reaching out to your backend.
One way to do this is the following:
// 1. Create a protocol for your data provider:
protocol UserProvider {
func getUsers() async -> [User]
}
// 2. Next is to create your real data provider and a mock version:
class ApiUserProvider: UserProvider {
func getUsers() async -> [User] {
return await someRequest()
}
}
class DummyUserProvider: UserProvider {
func getUsers() async -> [User] {
return [User(), User()]
}
}
// 3. Now in your client code, you can use the type UserProvider instead of ApiUserProvider
class SomeClient {
init(userProvider: UserProvider) { /* …. */ }
}
This approach makes your code suitable for unit testing as it removes all the uncontrollable factors from the unit you are testing. One downside of it is that while developing, you will not see all the edge cases that comes with real networking or that sometimes you can end up over-engineering your code just to abstract out every piece of the networking layer
Mocking your network layer
The next option is to mock your network layer. In this case you are altering how your networking client behaves in certain situations. To do this on iOS, you can create a custom type conforming the URLProtocol protocol. This protocol allows you to stop a URLSession from making a request and instead return any data you want it to return.
To use it, create your protocol, then set it like this:
let configuration: URLSessionConfiguration = .ephemeral
configuration.protocolClasses = [YourProtocolType.self]
let session = URLSession(configuration: configuration)
This approach will still eliminate the networking from your application but is one step closer to a hassle free solution where you are not required to over engineer your code
Setting up a local deserver manually
If you want to see how your app really behaves while communicating over the network while still having full control over the API you are talking to, one of your best options is to set up a local server. You can do this in many ways. One of them is using Node.js with express:
// 1. Create a node project
// 2. Add the following code to your index.js
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
This is a quick and easy solution. It is fully customisable and doesn’t eliminate any of the nuances of having real networking in your application. The only downside is having to code a backend for your app. Even if this backend is a development one with hardcoded data and simplified logic, you still have to work on it and as you start adding more advanced features, like authentication or file responses, it quickly becomes a rather tedious task. This is where our last option comes in play
Using a mock server application
By using an app that allows you to set up mock servers, you get the best parts of the previous solution while leaving the implementation to the developers of the app. One such app is MockaMatic.
To set up a mock server with MockaMatic, follow these few easy steps:
0. Install the app
MockaMatic can be installed from the Mac and iOS App stores
1. Createa a mock server
Once the app is installed, click the plus button or press cmd+n on the Mac to create a new mock server
Enter a name for your server and adjust the port if needed
2. Add the routes
Add any number of routes you would like to mock. For each route you can specify a path, the request method it is listening to and what the response’s status code and body to be. You can also set up an authentication method so the route will automatically reject any request that doesn’t match a certain criteria
3. Once you saved your server, you can start it by pressing the play button
4. Review your requests
While the server is running, you can keep an eye on the incoming requests using the server status view in the app or in the status bar area in case you are using MockaMatic on the Mac
Latest articles
Here are some more articles that may interest you. Check them out!
The reentrancy problem
When a new feature is introduced in a programming language, we as developers are often quick to assume it will solve many of their challenges. The excitement to experiment with such features is natural, but it’s often accompanied by the realisation that every solution brings its own set of unique challenges. This was no different when actors were introduced.
Read moreTips and tricks for iOS & macOS cross platform development
You may have heard how incredibly easy it is to develop user interfaces that work well in all platforms with SwiftUI. But I have some bad news for you, while SwiftUI indeed makes our lives a lot easier, you will still have to invest some time to get the best results out of it.
Read moreDebugging memory leaks in Xcode
Ever got into a situation where you observed some strange behaviour with your app? Crashes, very bad performance or strange warnings in the console? Or simply you looked at the memory usage of your app and realised that it’s way too high for what your app should be doing? Yeah! Most likely you are dealing with a memory leak.
Read more