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
URLProtocolsubclass and implement the above given obligatory strategies
- Register your
URLProtocolsubclass with the system in your AppDelegate’s
- Assign the kind of your URLProtocol subclass to the
URLSession. 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:
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.
We’ll use this mannequin object to set the
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.
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.
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.
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
We’re now all set! Let’s begin writing the assessments.
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
viewmannequin 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]
URLSessionProxyto return a mock response
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.