Swift中的可测试网络层—第1部分
在编写程序时,根据编码最佳实践,代码应具有可读性,可维护性和可测试性 。
“无法测试的代码存在缺陷。”
作为iOS移动应用程序开发人员 ,我们经常编写许多涉及UI,网络,持久性和其他业务逻辑的代码。 在本文中,我们将共享我们的网络层实现,该实现处理API / web-service交互,以帮助编写有关网络层逻辑的测试。
在编写测试之前,我们需要熟悉如何将网络层代码与UI相关代码和其他业务逻辑分离。 没有这种去耦,就不可能孤立地测试网络层。
网络层包括:
- 准备请求 (URL,方法类型,标题,参数)
- API调用 (NSURLSession)
- 解析响应 (将数据转换为模型对象(或返回错误消息)
网络层测试使我们能够确保API请求已正确形成,并且API响应解析已按预期完成,从而模拟了Web服务器。
根据我们的测试方案,我们将需要进一步分离网络层。 为此,我们将创建一个APIHandler,该APIHandler用于发出请求并解析响应。
遵循APIHandler ,请参阅以下有关LoginAPI的示例请求/响应处理程序。
Path()
-不用担心Path()。login 。 Path()
只是一种根据DEV / TEST / RELEASE环境返回特定端点的方法。 更多详细信息可以在这里找到。
所有API请求都将包含url,httpMethod,参数和标头 。
set
—由于上述示例API调用是一种post方法,因此我们需要准备httpBody,这是通过RequestHandler协议扩展来完成的。
BaseRequest
对于所有常见的请求配置(例如标头,timeoutInterval等),我们可以创建一个符合Request Protocol的 BaseRequest
类, 如下所示。
设置好通用配置后,每个API可能会有要在API请求中发送的自定义参数。 对于需要身份验证令牌的任何API,我们可以使用AuthRequest对象而不是BaseRequest对象,以便API请求具有auth-token。
现在,我们已根据需要准备了URLRequest 。
准备好API请求后,我们可以调用API(我们将在一分钟内逐步完成)。 放置API调用并且服务器响应后,我们将收到需要根据我们的要求进行解析的原始响应。 通常,我们将原始响应解析为模型对象。 为此,我们可以使用泛型来处理ResponseHandler中的响应 。
上面的代码处理来自服务器的success
, known-error
和unknown-error
api响应
为了调用API,我们编写了一个通用类APILoader ,该类使用可达性库处理网络错误,URLSession和Internet连接错误,如下所示。
我们可以将LoginAPI对象传递给通用APILoader ,如下所示。
我们还可以将用户相关的API调用(如login,userDetails和deleteUser方法) 分组在单独的swift文件(如UserServices.swift)中,以提高可读性。
当用户与您的应用进行交互并且您的UI要求后端提供一些数据时,我们必须与NetworkLayer进行交互。 大多数情况下, 交互源来自于Presentation / Business / Repository层。 该层应与UserServices.swift文件方法进行交互,以通过API调用从服务器获取数据,如下所示。
根据要求,我们可以处理如下所示的特定错误类型:
关于上述LoginAPI结构中的makeRequest makeRequest(params…)
:请记住,如果我们尝试通过传递url,http方法等以及所需的输入参数来使此函数更通用,则会违反单一职责原则,该原则规定仅服务层应负责创建请求,因为业务/仓库层不负责处理服务。 这样,服务层与调用组件完全隔离,并且也是可测试的。
如本文所述,一旦代码解耦了网络层,就可以对其进行测试了。 本系列的第2部分(即将推出)将向您展示如何在NetworkLayer上编写测试。
您可以在下面找到源代码:
Appitventures / IOS博客
共享可以公开的与博客相关的文件– appitventures / IOS-Blog
github.com
这基于WWDC 2018 :“测试技巧和窍门”-感谢Apple的Brian Croom。
如上所述,一旦您的代码解耦了网络层,就可以进行测试了。 您可以在第2部分中知道如何在网络层上编写测试。