组件测试使用 Cypress 无法连接 WebSocket(SignalR)- WebSocket 握手超时

huangapple go评论64阅读模式
英文:

component test with cypress failing to connect Websocket(signalR)- WebSocket opening handshake timed out

问题

我们正在Cypress上编写一个组件测试,针对一个使用SignalR进行WebSocket通信的React-JS应用程序。Restful API是在dotnet core中开发的。

测试包含通常的cy.intercept命令,尝试模拟API。

在运行测试时,应用程序试图内部访问SignalR端点'/testhub',但失败并显示以下错误 -

WebSocketTransport.js:49 WebSocket连接到'ws://localhost:8080/testhub'失败:WebSocket打开握手超时

(未捕获的异常)错误:WebSocket连接失败。在服务器上找不到连接,可能端点不是SignalR端点,连接ID不存在于服务器上,或者有代理阻止WebSocket。如果您有多个服务器,请检查是否启用了粘性会话。

以下是测试文件:

describe('<Jobs Page>', () => {
        
   
    it('verify the data displaying in jobs page', () => {
        cy.viewport(1000,1000)

        //模拟API       
        cy.intercept("GET","api/jobs/testhub",{ fixture: 'testData.json'})       

        //安排或挂载组件
        cy.mount(<Job/>)

       
    })  
})

我们尝试使用"cypress-plugin-signalr"、"socket.io-mock"插件来模拟WebSocket,但没有取得任何成果。

另外,我们不确定SignalR期望的端点是什么?应用程序UI引用的是'http' URL,而SignalR端点期望的是'ws'。

英文:

We are writing component test in cypress on a React-JS application which uses signalR for the websocket. Restful APIs are developed in dotnet core.

The test contains of usual cy.intercept commands trying to mock the APIs

While running the test the application is trying to reach a signalR endpoint '/testhub' internally and failing out giving the following error -

> WebSocketTransport.js:49 WebSocket connection to 'ws://localhost:8080/testhub' failed: WebSocket opening handshake timed out
>
>(uncaught exception)Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.

Below is the test file:

describe(&#39;&lt;Jobs Page&gt;&#39;, () =&gt; {
        
   
    it(&#39;verify the data displaying in jobs page&#39;, () =&gt; {
        cy.viewport(1000,1000)

        //mocking the API       
        cy.intercept( &quot;GET&quot;,&quot;api/jobs/testhub&quot;,{ fixture: &#39;testData.json&#39;})       

        //Arranging or mounting a component
        cy.mount(&lt;Job/&gt;)

       
    })  


})

We tried using "cypress-plugin-signalr", "socket.io-mock" plugins and mocking the websocket, but nothing fruitful.

Also not sure what is the endpoint signalR is expecting? The application UI are referring to 'http' urls whereas signalR endpoint is expecting 'ws'.

答案1

得分: 4

这里有一个教程 使用 Cypress 测试 Socket.io 聊天应用 可以帮到你。

有几种连接的策略显示如何连接:

  • 使用任务(请注意,该代码适用于 Cypress v10 之前的配置)

  • 在测试中使用 socket.io-client 连接

这第二种方法使用套接字事件而不是 cy.intercept()。我无法确定你的协议是什么,但以下似乎是一个合理的近似。

const fixtureData = require('cypress/fixtures/testData.json')
const io = require('socket.io-client')
const socket = io.connect('ws://localhost:8080/testhub')

it('验证作业页面中显示的数据', () => {

  // 使用套接字捕获消息
  socket.on('get_data', () => {           // 检查哪个消息发起数据获取
    socket.emit('data', fixtureData)      // 同样,适当修改此消息
  })

  cy.mount(<Job/>)

  ...
})
英文:

There is a tutorial here Test a Socket.io Chat App using Cypress that should help you.

There are a couple of strategies shown on how to connect

  • using a task (note the code is for pre Cypress v10 configuration)

  • using socket.io-client connection in test

This second approach uses socket events rather than cy.intercept(). I can't tell what your protocol is, but the following seems a reasonable approximation.

const fixtureData = require(&#39;cypress/fixtures/testData.json&#39;)
const io = require(&#39;socket.io-client&#39;)
const socket = io.connect(&#39;ws://localhost:8080/testhub&#39;)

it(&#39;verify the data displaying in jobs page&#39;, () =&gt; {

  // use socket to catch messages
  socket.on(&#39;get_data&#39;, () =&gt; {           // check what message initiates data fetch
    socket.emit(&#39;data&#39;, fixtureData)      // also modify this message appropriately
  })

  cy.mount(&lt;Job/&gt;)

  ...
})

答案2

得分: 0

我创建了自己的插件,基于"cypress-plugin-signalr",名为:Cypress-SignalR-Mock

一个简单的使用示例

// 01. 在创建SignalR连接的位置导入插件。
import { useCypressSignalRMock } from 'cypress-signalr-mock';

// 02. 调用"useCypressSignalRMock"来创建SignalR hub连接的模拟,确保为其提供唯一的hub名称。当Cypress未运行时,它将返回null。
const progressHubConnection = useCypressSignalRMock('progress') ??
    new HubConnectionBuilder().withUrl(`http://localhost:3000/progress`).build();

// 03. 在cypress/support/index.[js/ts]文件中激活插件。
import 'cypress-signalr-mock';

// 04. 在您的E2E测试中使用'hubPublish()'来发布消息,就像是服务器一样。
cy.hubPublish(
    'progress', // hub的名称
    'hello-world', // 消息类型的名称
    {
        message: 'Hello World!', // 消息负载
    },
);

// 05. 监听器将正常接收消息。
progressHubConnection.on('hello-world', (data) => {
    console.log(data); // { message: 'Hello World!' }
});
英文:

I created my own plugin that is based on "cypress-plugin-signalr" called: Cypress-SignalR-Mock

A simple usage example:

// 01. Import the plugin to where your signalR connections are created.
import {useCypressSignalRMock} from &#39;cypress-signalr-mock&#39;;

// 02. Call &quot;useCypressSignalRMock&quot; to create a mock for the SignalR hub connection, 
// make sure to give it an unique hub name. It will return null when Cypress is not running.
const progressHubConnection = useCypressSignalRMock(&#39;progress&#39;) ??
    new HubConnectionBuilder().withUrl(`http://localhost:3000/progress`).build();

// 03. Activate the plugin in your cypress/support/index.[js/ts] file.
import &#39;cypress-signalr-mock&#39;;

// 04. Use &#39;hubPublish()&#39; in your E2E tests to publish messages as if it&#39;s the server.
cy.hubPublish(
    &#39;progress&#39;, // The name of the hub
    &#39;hello-world&#39;, // The name of the message type
    {
        message: &#39;Hello World!&#39;, // The message payload
    },
);

// 05. The listener will receive the message as normal.
progressHubConnection.on(&#39;hello-world&#39;, (data) =&gt; {
    console.log(data); // { message: &#39;Hello World!&#39; }
});

huangapple
  • 本文由 发表于 2023年5月29日 20:35:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76357428.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定