Harness the facility of integration testing in your iOS apps
That is the place you run take a look at circumstances when all of your modules work collectively. In the true world, no module will ever operate in isolation. There may be all the time a circulate of knowledge between totally different modules. That is the explanation bugs can happen even when your whole unit take a look at circumstances move. So, you will need to have integration assessments along with unit assessments.
A lot of the apps on the market talk with some type of backend. Notably, the community layer is liable for speaking with the backend and the information from this layer drives the applying. Due to this fact, it will be important that this layer features correctly, not solely in isolation but additionally together with different modules.
The core thought is to fully management the response (information
), standing code (HTTPURLResponse
), and the error (error
) that will get despatched upwards from the community layer. By controlling these parameters, we will simulate totally different eventualities and examine if our information parsing logic (decoding response), enterprise layer logic (View
mannequin or Presenter) and all different modules behave as anticipated.
We are able to additionally study the community requests made to our URLSession
occasion by our community layer and examine if they’re as anticipated.
Disclaimer: I’ve deliberately averted finest practices to maintain the code easy for this text.
Right here we use a shared occasion of the URLSession
to make a community name. Normally, the system takes care of performing this community name and returns the end result.
However the system additionally provides you an opportunity to carry out the request your self and return again the end result. Utilizing URLProtocol
is the way in which to do it.
Let’s get began:
- Create a
URLProtocol
subclass and implement the above given obligatory strategies - Register your
URLProtocol
subclass with the system in your AppDelegate’ssoftware (_:didFinishLaunchingWithOptions:)
technique. - Assign the kind of your URLProtocol subclass to the
protocolClasses
property ofURLSession
. Don’t create an occasion of your subclass since that is taken care of by the system mechanically.
Now, each time URLSession
is requested to make a community request, it can first examine with the objects within the protocolClasses
array and ask in the event that they need to deal with the request by calling canInit(with: request) — > Bool
. By returning true from our subclass, we are going to get an opportunity to deal with the request.
We have now an app the place a person can see an inventory of posts [String]. Let’s name it the person feed. We have now three modules right here:
1. Community layer
It makes use of the URLSession
’s shared occasion to make community requests and decodes the response utilizing JSONDecoder.
2. View Mannequin
It helps fetching and looking posts, utilizing the community layer.
3. View Controller
It has an occasion of the view mannequin and conforms to the ViewModelDelegate
protocol. It invokes the view mannequin’s features and receives a reply by way of delegate callbacks.
We are able to write unit take a look at circumstances to confirm each module’s behaviour in isolation, however what if they begin behaving unexpectedly once they all begin interacting with one another? That is why we are going to write a number of integration assessments to confirm their behaviour.
Earlier than we begin writing our assessments, let’s full our URLSessionProxy
, as proven under:
Don’t shut the article 🤣. Let me break down what’s going on:
startLoading()
This technique is known as by the system after we conform to deal with an URL request by returning true inside func canInit(with request: URLRequest) -> Bool
. We’re supposed to start out processing the request and inform the shopper when finished.
RequestHandler
We’ll use this mannequin object to set the response
, information
, or error
for requests.
Static properties on URLSessionProxy
We have now a number of static properties that can be utilized to configure our class. They should be static for the reason that system takes care of making the precise occasion and we won’t have entry to this occasion.
contactedURLs: [URL]
This shops the record of URLs which might be handed by the system. This array will be helpful to look at the record of URLs that have been accessed by our software.
2. shouldHandleRequest: ((URLRequest) -> Bool) = _ in true
You should utilize this closure to resolve whether or not you need to deal with a specific request. That is invoked inside func canInit(with request: URLRequest) -> Bool
.
3. handleRequest: ((URLRequest) -> RequestHandler)
?
That is invoked inside func startLoading()
. You should utilize this closure to resolve the way you need to reply to an URLRequest
by returning an occasion of RequestHandler
.
We’re now all set! Let’s begin writing the assessments.
Expectation: URLSessionProxy
’s contactedURLs
array incorporates the person feed API Url.
We configure our URLSessionProxy
to return a default occasion of RequestHandler
occasion since we aren’t centered on that half on this take a look at. Then, we invoke viewDidLoad()
on the view
mannequin to kick off the method.
We wait till our expectation has been fulfilled after which make the most of our contactedURL
’s property on URLSessionProxy
to examine if our app contacted the person feed API as anticipated.
Expectation: On invoking viewDidLoad()
, view mannequin incorporates mock posts after it calls reloadPosts()
on its delegate.
We arrange the next:
- Create a
view
mannequin delegate and fulfill an expectation on the delegate technique name, in order that we all know that its time to examine the view mannequin for the mock posts [String] - Configure
URLSessionProxy
to return a mock response - Name
viewDidLoad()
on the view mannequin to start out the method
When the expectation is fulfilled, we examine if our view mannequin incorporates our mock posts. This take a look at will give us the boldness that each the community layer and consider mannequin are working collectively correctly to show the posts to the person.
Expectation: Search API is known as with the proper parameters
We configure our URLSessionProxy
to seize the search URLRequest
and reserve it to our native variable.
We then invoke the search technique on our view mannequin after which wait till our URLRequest
is captured.
We then study totally different components of our URLRequest
to examine if all of the parameters are as anticipated.