揭开Nestjs Websocket网关的神秘面纱:有效测试的分步指南
#网络开发人员 #教程 #node #nestjs

介绍

在不断发展的实时应用程序世界中,WebSocket Communication已成为一种强大的工具,可以在客户和服务器之间建立无缝有效的连接。 Nestjs是一种流行的打字稿框架,已将Websocket Gateways合并,以简化其生态系统中的实时通信。尽管使用Nestjs实施WebSocket功能无疑令人兴奋,但确保其可靠,有效地起作用至关重要。这就是测试起关键作用的地方。

欢迎获得有关为Nestjs Websocket网关创建测试的综合指南。在本文中,我们将研究Websocket Gateways的基础知识,并演示如何制定强大而有效的测试以验证其行为。

您是想扩大知识的经验丰富的Nestjs开发人员还是热衷于探索Websocket网关的新移民,本文将为您提供有价值的见解和实用示例,以开始掌握在Nestjs中测试实时功能的艺术应用。

第1部分:设置您的Nestjs Websocket网关:逐步指南

在我们指南的第一部分中,我们将带您完成设置具有WebSocket功能并生成聊天网关的Nestjs应用程序的过程。在本节结束时,您将有一个坚实的基础,可以开始构建基于WebSocket的应用程序并为其编写测试。

步骤1:安装Nestjs CLI

要开始,请确保您在计算机上安装了node.js。

如果您尚未安装Nestjs命令行界面(CLI),则可以通过运行以下命令在全球上进行:

npm i -g @nestjs/cli

步骤2:创建一个新的NEST应用程序

安装了Nestjs CLI后,通过执行以下命令来创建一个新的Nest应用程序:

nest new nest-app

在设置过程中,您将提示您选择一个软件包管理器。对于本教程,我们将使用NPM,因此请在提示时继续选择它。

Image description

Image description

生成应用程序后,使用以下命令导航到项目目录:

cd nest-app

步骤3:安装所需软件包

为了将Websocket功能添加到我们的应用程序中,我们需要安装必要的软件包。运行以下命令以安装 @nestjs/websockets和 @nestjs/platform-socket.io:

npm i --save @nestjs/websockets @nestjs/platform-socket.io

步骤4:生成聊天网关

安装了所需的软件包,让我们创建聊天网关。网关将处理Websocket连接并促进实时通信。使用Nest CLI生成聊天网关样板代码:

nest generate gateway chat

Image description

此命令将创建名为chat.gateway.ts and Chat.gateway.spec.ts的新文件,您可以使用您选择的文本编辑器打开它:

vim src/chat/chat.gateway.ts

在打开聊天网关文件时,您将找到网关的基本结构,包括带有WebSocketGateway装饰器的类定义。我们将基于此结构并随着文章的发展而添加更多功能。

恭喜!此时,您已经成功地设置了具有WebSocket功能的Nestjs应用程序,并生成了聊天网关。在下一节中,我们将深入研究Websocket网关并开始编写测试以确保其适当的功能。

第2部分:实施聊天网关并了解代码

在本节中,我们将用更丰富的Chatgateway实现替换样板代码。我们将探索代码的每个部分,了解其目的,并讨论我们所做的更改。

在我们研究代码之前,让我们简要介绍网关中使用的每个接口和装饰器的目的:

  • @WebSocketGateway():此装饰器将同类标记为Websocket网关,允许其处理Websocket连接和事件。

  • @WebSocketServer():此装饰器将Websocket Server实例(socket.io实例)注入网关,启用与已连接的客户的直接通信。

  • OnGatewayInit:此接口提供了一个方法afterInit(),该方法在初始化WebSocket网关时将执行。这是执行与网关初始化有关的任何设置或记录的好地方。

  • OnGatewayConnection:此接口提供了一个方法handleConnection(client: any, ...args: any[]),该方法在建立新的WebSocket连接时被调用。在这里,您可以处理与客户连接有关的任务,例如记录或广播欢迎消息。

  • OnGatewayDisconnect:此接口提供了一个方法handleDisconnect(client: any),该方法在websocket client断开连接时会触发。您可以使用此方法执行任何清理任务或记录断开事件。

  • @SubscribeMessage('ping'):此装饰器指出,handleMessage(client: any, data: any)方法将使用从客户端发送的事件名称“ ping”处理消息。在我们的情况下,它只是记录了收到的消息并返回一个名为“ Pong”的响应事件,并带有固定的响应数据。

现在,让我们仔细看看我们对Chatgateway所做的代码更改:

import { Logger } from "@nestjs/common";
import {
  OnGatewayConnection,
  OnGatewayDisconnect,
  OnGatewayInit,
  SubscribeMessage,
  WebSocketGateway,
  WebSocketServer,
} from "@nestjs/websockets";

import { Server } from "socket.io";

@WebSocketGateway()
export class ChatGateway
  implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
  private readonly logger = new Logger(ChatGateway.name);

  @WebSocketServer() io: Server;

  afterInit() {
    this.logger.log("Initialized");
  }

  handleConnection(client: any, ...args: any[]) {
    const { sockets } = this.io.sockets;

    this.logger.log(`Client id: ${client.id} connected`);
    this.logger.debug(`Number of connected clients: ${sockets.size}`);
  }

  handleDisconnect(client: any) {
    this.logger.log(`Cliend id:${client.id} disconnected`);
  }

  @SubscribeMessage("ping")
  handleMessage(client: any, data: any) {
    this.logger.log(`Message received from client id: ${client.id}`);
    this.logger.debug(`Payload: ${data}`);
    return {
      event: "pong",
      data: "Wrong data that will make the test fail",
    };
  }
}

在上面的代码中,我们用更有功能的实现替换了先前的样板网关:

  1. 我们从@nestjs/common@nestjs/websockets导入了所需的模块和类,以及'socket.io'的Server class。

  2. 我们使用@nestjs/common定义了一个记录器,以方便网关内的记录。该记录仪在测试过程中将很有帮助。

  3. afterInit()方法中,我们记录了一条简单的消息,指示Websocket网关已初始化。这对于跟踪应用程序的生命周期可能很有用。

  4. handleConnection(client: any, ...args: any[])方法中,我们处理了一个新的WebSocket连接。我们记录了客户端的ID和连接客户端的总数,以跟踪活动连接。

  5. handleDisconnect(client: any)方法负责记录断开事件。当Websocket客户端断开连接时,将调用此方法执行任何必要的清理或记录。

  6. 我们实现了一个名为handleMessage(client: any, data: any)@SubscribeMessage('ping')方法。此方法处理连接客户端的事件名称“ ping”的传入消息。它将收到的消息与其有效载荷一起记录,并返回一个名为“ Pong”的固定响应事件,其中包含有意错误的消息的数据字段。我们添加了这个故意的错误,以说明如何在即将到来的部分中测试错误行为。

使用新的ChatGateway,我们的WebSocket应用程序现在可以处理客户的连接,断开连接和传入的消息。在本文的下一部分中,我们将重点介绍该网关的编写测试,以确保其适当的功能和鲁棒性。

第3部分:Nestjs Websocket网关编写测试

在指南的最后一部分中,我们将探讨如何为我们之前创建的Chatgateway编写测试。在本节结束时,您将进行一套测试,以确保您的Websocket网关可靠地和预期。

让我们打开测试文件:

vim src/chat/chat.gateway.spec.ts

并将样板代码替换为以下测试:

import { Test } from "@nestjs/testing";
import { ChatGateway } from "./chat.gateway";
import { INestApplication } from "@nestjs/common";
import { Socket, io } from "socket.io-client";

async function createNestApp(...gateways: any): Promise<INestApplication> {
  const testingModule = await Test.createTestingModule({
    providers: gateways,
  }).compile();
  return testingModule.createNestApplication();
}

describe("ChatGateway", () => {
  let gateway: ChatGateway;
  let app: INestApplication;
  let ioClient: Socket;

  beforeAll(async () => {
    // Instantiate the app
    app = await createNestApp(ChatGateway);
    // Get the gateway instance from the app instance
    gateway = app.get<ChatGateway>(ChatGateway);
    // Create a new client that will interact with the gateway
    ioClient = io("http://localhost:3000", {
      autoConnect: false,
      transports: ["websocket", "polling"],
    });

    app.listen(3000);
  });

  afterAll(async () => {
    await app.close();
  });

  it("should be defined", () => {
    expect(gateway).toBeDefined();
  });

  it('should emit "pong" on "ping"', async () => {
    ioClient.connect();
    ioClient.emit("ping", "Hello world!");
    await new Promise<void>((resolve) => {
      ioClient.on("connect", () => {
        console.log("connected");
      });
      ioClient.on("pong", (data) => {
        expect(data).toBe("Hello world!");
        resolve();
      });
    });
    ioClient.disconnect();
  });
});

在此测试文件中,我们使用@nestjs/testing软件包来设置测试模块并编译以创建Nestjs应用程序实例。 createNestApp()功能将ChatGateway作为参数,并返回初始化的应用程序。

然后,我们创建一个socket.io client(ioClient),该客户端连接到http://localhost:3000的Websocket服务器。 autoConnect: false选项可确保客户端不会自动连接,我们将传输指定为“ Websocket”和“轮询”,以便Websocket连接是默认的尝试连接选项。

现在,让我们浏览我们写过的两个测试:

  1. 第一个测试只需检查Chatgateway是否定义。我们希望该网关在实例化后定义。这确保了网关设置正确并准备好处理WebSocket连接。

  2. 第二个测试模拟了从客户端到服务器的“ ping”事件。我们希望服务器以“ pong”事件做出响应,其中包含与“ ping”事件中发送的相同数据的响应。但是,当前的handleMessage()实现在响应中返回错误的数据,这导致测试失败。

要运行测试,首先安装socket.io-client软件包:

npm install -D socket.io-client

注意:您不需要安装 @types/socket.io-client类型,因为它已经在主软件包中。

并在另一个外壳窗口中使用以下命令:

npm run test:watch

在观察模式下运行的测试套件,对Chatgateway或测试文件进行的任何更改都会触发测试自动重新运行,以确保您的Websocket网关在整个开发过程中保持强大并进行了适当的测试。

一个测试未预期。

要在网关的handleMessage()方法中修复错误,请如下更新:

@SubscribeMessage("ping")
handleMessage(client: any, data: any) {
  this.logger.log(`Message received from client id: ${client.id}`);
  this.logger.debug(`Payload: ${data}`);
  return {
    event: "pong",
    data,
  };
}

现在,通过正确实施,测试应成功通过。

恭喜!您已经成功设置并测试了Nestjs Websocket网关。凭借有关如何测试WebSocket功能的知识,您可以自信地使用Nestjs开发实时应用程序,因为您知道您的WebSocket通信是可靠且高效的。

感谢您加入我的旅程,与Nestjs一起探索WebSocket网关!我希望您对您的实时申请开发努力发现本指南的信息和有价值。

如果您喜欢阅读本文并发现它有帮助,请考虑对其进行大拇指或在下面发表评论。您的反馈和参与鼓励我创建更多这样的内容,帮助社区一起学习和成长。

愉快的编码,并希望您的Websoket-Power应用程序随着Nestjs的身份蓬勃发展! ðð