cypress从React组件中间谍函数调用

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

cypress spy on function call from react component

问题

我想监听一个在单独文件中定义并由多个React组件调用的函数。

例如,我有这个test.js文件:

export const func = {
  call: (e) => console.log(e),
};

这被多个React组件导入,我想用Cypress监听这个函数,但它从未被调用:

import { func } from "../../src/test";

describe("template spec", () => {
  it("calls func.call", () => {    
    cy.visit("/");
    cy.spy(func, "call");
    //更多的代码...
    expect(func.call).to.be.called
  });
});

我的测试目标是验证应用程序与后端之间的网络流量,包括通过REST和Socket.io的双向通信。因为需要应用程序可以在没有真正后端的情况下进行演示和测试,所以我模拟了fetch函数和Socket事件以模拟后端,可以通过环境变量启用。测试需要能够在没有运行后端的情况下运行。问题在于,一方面我需要一种方法来测试我的Socket.io流量,这在Cypress中似乎不可能,另一方面,对于fetch,cy.intercept的工作方式与预期不同。我成功拦截了fetch调用并将它们重定向到我的模拟函数,但似乎原始的fetch主体已经被序列化了,我不能轻松获取原始的fetch主体。特别是涉及到FormData主体时,这一点特别棘手。

我是Cypress测试的新手,所以我可能对监听的概念有所误解。我做错了什么?

英文:

I want to spy on a function which is defined in a separate file and called by multiple react components.

for example I have this test.js file:

export const func = {
  call: (e) => console.log(e),
};

This is imported by multiple React components and i want to spy on this function with cypress but its never called:

import { func } from "../../src/test";

describe("template spec", () => {
  it("calls func.call", () => {    
    cy.visit("/");
    cy.spy(func, "call");
    //some more code ...
    expect(func.call).to.be.called
  });
});

The goal of my test is to validate the network traffic from my app to the backend and backwards over rest and socket.io. Because its necessary that the app can be used without the real backend for presentation and testing purpose i mocked the fetch function and socket events to simulate the backend which can be enabled by an environment variable. And its required that the test can run without the backend running. The problem is on the one hand that i need a possibility to test my socket.io traffic which is not possible with cypress like i read and on the other hand that cy.intercept for fetch is not working as expected. I manged to intercept the fetch calls and redirect them to my mockfunction but it seems that the original fetch body is already kind of serilized and i can not easily get the original fetch body. This is especially tricky when it comes to formdata body.

I'm new to testing with cypress, so i might have misunderstood the concept of spying. What am i doing wrong?

答案1

得分: 3

我可以回答关于你的间谍问题。

当你在测试中导入 func 时,你得到的是一个与应用程序使用的不同的函数实例。

如果你想成功地监视它,你必须将应用程序中的相同实例传递给测试。

这样做的一种被接受的方式是将 func 放在 window 对象上。例如,在 React 代码的 App.js 文件中:

import React from 'react';
import { func } from "../../src/test";

if (window.Cypress) {   // 检查是否运行了 Cypress
  window.func = func
}

function App() {
  const greeting = 'Hello Function Component!';

  return <h1>{greeting}</h1>;
}

export default App;

现在在你的测试中,你可以像这样成功监视 func

it("calls func.call", () => {    

  cy.visit('/', {
    onBeforeLoad: (window) => {          // 重要:间谍必须首先设置!!!
      cy.spy(window, 'func').as('func')  // 监视 func 属性,设置别名
  })

  // 更多代码 ...

  cy.get('@func').should('have.been.called')
})

参考:更多示例请查看 Bahmutov - Spies, Stubs & Clocks

英文:

I can answer the question about your spy.

When you import func inside the test you are getting a different instance of the function to the one the app is using.

If you want to successfully spy on it, you must pass the same instance from the app to the test.

The accepted way to do that is to put func on the window object. For example, in App.js in the React code

import React from &#39;react&#39;;
import { func } from &quot;../../src/test&quot;

if (window.Cypress) {   // check if Cypress is running
  window.func = func
}

function App() {
  const greeting = &#39;Hello Function Component!&#39;;

  return &lt;h1&gt;{greeting}&lt;/h1&gt;;
}

export default App;

Now in your test, you will successfully spy on func like this

it(&quot;calls func.call&quot;, () =&gt; {    

  cy.visit(&#39;/&#39;, {
    onBeforeLoad: (window) =&gt; {          // IMPORTANT spy must be set first!!! 
      cy.spy(window, &#39;func&#39;).as(&#39;func&#39;)  // spy on func property, setting an alias
  })

  //some more code ...

  cy.get(&#39;@func&#39;).should(&#39;have.been.called&#39;)
})

Reference: for more examples Bahmutov - Spies, Stubs & Clocks

答案2

得分: -1

为了测试WebSocket,有一个用于Cypress的库

https://github.com/lensesio/cypress-websocket-testing

同样也在Cypress插件网页上列出。

https://docs.cypress.io/plugins

在这里,你会找到许多插件,它们将帮助你解决许多未来的问题。

希望这有所帮助。
英文:

To test the WebSocket, There is a library for Cypress

https://github.com/lensesio/cypress-websocket-testing

The same is also listed on the Cypress plugin webpage.

https://docs.cypress.io/plugins

Here you'll find many plugins which will help you with many of your future problems.

Hope this helps.

huangapple
  • 本文由 发表于 2023年8月10日 19:48:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76875465.html
匿名

发表评论

匿名网友

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

确定