Go: WebSockets单元测试
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go: WebSockets单元测试相关的知识,希望对你有一定的参考价值。
参考技术A WebSockets通过TCP连接提供客户端与服务器之间的双向即时通信。这意味着,我们可以维护一个TCP连接,然后发送和监听该连接上的消息,而不是不断地通过新建TCP连接去轮询web服务器的更新。在Go的生态中,WebSocket协议有几个不同的实现。有些库是协议的纯实现。另外一些人则选择在WebSocket协议的基础上构建,为他们特定的用例创建更好的抽象。
下面是一个不全面的Go WebSocket协议实现列表:
在线拍卖是以实时通信为核心的行业之一。在一场拍卖中,几秒钟的时间就决定了你是赢了还是失去了一件你一直想要的收藏品。
让我们以gorilla/websocket库实现的简单拍卖应用程序作为本文的示例。
首先,我们将定义两个非常简单的结构体Bid和Auction,我们将在WebSocket处理程序中使用它们。 Auction 有一个Bid方法,我们将使用该方法接收客户端发送来的竞价请求。
这两种类型都相当简单,包含的字段非常少。NewAuction构造函数构建一个带有持续时间、itemID和*Bids的Aution实例。
我们将通过 Bid 方法来实现拍卖的竞标动作:
Auction的Bid方法就是物品竞拍发生的地方。它接收一个 amount 和 userID 作为参数,并向 Auction 对象中添加Bid实例。而且它会检查竞拍是否结束以及的竞拍价格是否大于已有的最大竞价。如果这些条件中的任何一个不满足,它将向调用者返回适当的错误。
有了结构体定义和Bid方法,让我们深入到WebSockets机制。
想象一下,一个可以在拍卖中实时出价的网站。它通过WebSockets发送的每一条JSON消息都会包含用户的标识符( UserID )和出价的金额( amount )。一旦服务器接受了消息,它将参与竞价并向客户端返回一个竞拍结果。
在服务器端,此通信将由 net/http 处理程序完成。它将处理所有WebSocket的业务逻辑,有几个值得注意的步骤:
1、将接收到的HTTP连接升级为WebSocket连接。
2、接收来自客户端的消息。
3、从消息中解码出bid对象。
4、参与竞价。
5、 向客户端发送竞拍结果。
下面我们来实现这个处理程序。首先定义 inbound 和 outbound 消息类型,用于接收和发送客户端消息。
它们都分别表示入站/出站消息,这就是在客户端和服务器之间的交互数据。 inbound 入站消息将表示一个出价,而 outbound 类型表示一个简单的返回消息,其Body中包含一些文本。
接下来定义 bidsHandler ,包含ServeHTTP方法实现HTTP连接的升级:
首先定义 websocket.Upgrader ,接收处理程序的 http.ResponseWriter 和 *http.Resquest 并升级连接。 因为这只是一个应用程序示例 upgrader.CheckOrigin 方法将只返回true,而不检查传入请求的来源。一旦 upgrader 完成连接的升级,将返回 *websocket.Conn 对象保存在 ws 变量中。 *websocket.Conn 将接收所有客户端发送来的消息,也是处理程序读取请求内容的地方。同样,处理程序将会向 *websocket.Conn 写入消息,它将向客户端发送响应消息。
for 循环做了几件事:首先,使用 ws.ReadMessage() 读取websocket消息,改函数返回消息类型(二进制或文本)和消息内容( m )以及可能发生的错误( err )。然后,检查客户端是否意外地关闭了连接。
错误处理完成并读取到消息,我们将使用 json.Unmarshal 对其进行解码。接着调Bid方法参与竞拍。然后使用 json.Marshal 对返回内容进行序列化,使用 ws.WriteMessage 方法发送给客户端。
尽管编写WebSocket处理程序比普通HTTP处理程序要复杂得多,但测试它们很简单。事实上,测试WebSockets处理程序就像测试HTTP处理程序一样简单。这是因为WebSockets是在HTTP上构建的,所以测试WebSockets使用的工具与测试HTTP服务器相同。
首先添加测试用例:
首先,我们从定义测试用例开始。每个用例有一个 name ,这是测试用例的可读名称。此外,每个测试用例都有一个 bids 切片和一个duration持续时间,用于创建一个测试拍卖对象 Auction 。测试用例还有一个入站消息 inbound 和一个出站回复 outbound —这是测试用例将发送给处理程序并期望从处理程序返回的消息。
在TestBidsHandler中我们添加三种不同的测试用例——一个是客户端发起了错误的报价,低于目前最大报价,另一个测试用例,客户端添加了一个正常的报价,第三个客户端参与的拍卖已结束。
下面完成测试函数:
我们在subtest函数体中添加了一些新函数。 newWSServe r将创建一个测试服务器并将其升级为WebSocket连接,同时返回服务器和WebSocket连接。然后, sendMessage 函数将通过WebSocket连接将消息从测试用例发送到测试服务器。之后,通过 receiveWSMessage ,我们将从服务器读取响应,并通过将其与测试用例的进行比较来断言其正确性。
那么,这些新的函数的作用是什么呢?让我们逐一分析。
newWSServer 函数使用 httptest.NewServer 函数将处理程序挂载到测试HTTP服务器上。通过 httpToWS ,实现了将服务器的 URL 转为websocket URL (它只是将URL中的 http 协议替换为 ws ,或将 https 替换为 wss 协议)。
为了建立WebSocket连接,我们使用 WebSocket.DefaultDialer ,它是一个所有字段都设置为默认值的dialer。调用 Dial 方法通过WebSocket服务器URL (wsURL)返回WebSocket连接。
sendMessage 函数接收一个WebSocket连接和 inbound 消息作为参数。将消息序列化成json以二进制格式在websocket连接中发送。
receiveWSMessage 函数以 ws WebSocket连接为参数,通过 ws.ReadMessage() 读取请求消息,然后反序列化成 outbound 类型返回。
如果我们运行测试,我们将看到它们通过:
以上是关于Go: WebSockets单元测试的主要内容,如果未能解决你的问题,请参考以下文章