Swift中的可测试网络层—第1部分

在编写程序时,根据编码最佳实践,代码应具有可读性,可维护性和可测试性

“无法测试的代码存在缺陷。”

作为iOS移动应用程序开发人员 我们经常编写许多涉及UI,网络,持久性和其他业务逻辑的代码。 在本文中,我们将共享我们的网络层实现该实现处理API / web-service交互,以帮助编写有关网络层逻辑的测试。

在编写测试之前,我们需要熟悉如何将网络层代码与UI相关代码和其他业务逻辑分离。 没有这种去耦,就不可能孤立地测试网络层。

网络层包括:

  • 准备请求 (URL,方法类型,标题,参数)
  • API调用 (NSURLSession)
  • 解析响应 (将数据转换为模型对象(或返回错误消息)

网络层测试使我们能够确保API请求已正确形成,并且API响应解析已按预期完成,从而模拟了Web服务器。

根据我们的测试方案,我们将需要进一步分离网络层。 为此,我们将创建一个APIHandler,APIHandler用于发出请求并解析响应。

遵循APIHandler ,请参阅以下有关LoginAPI的示例请求/响应处理程序

Path() -不用担心Path()。loginPath()只是一种根据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中的响应

上面的代码处理来自服务器的successknown-errorunknown-error api响应

为了调用API,我们编写了一个通用类APILoader ,该类使用可达性库处理网络错误,URLSession和Internet连接错误,如下所示。

我们可以将LoginAPI对象传递给通用APILoader ,如下所示。

我们还可以将用户相关的API调用(如login,userDetailsdeleteUser方法) 分组在单独的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部分中知道如何在网络层上编写测试。