如何用开玩笑和酶在使用效果内测试功能?

发布于 2025-01-23 02:16:28 字数 1058 浏览 2 评论 0原文

我正在使用开玩笑和酶测试组件。我想加载整个页面时加载

const RatingsAndReviews = (props: RatingsAndReviewsProps) => {

const [pageLoaded, setPageLoaded] = useState<boolean>(false)

const handleLoad = () => {
    if (document.readyState === 'complete') {
      setTimeout(() => {
        setPageLoaded(true)
      }, 1500)
    }
}

React.useEffect(() => {
    window.addEventListener('load', handleLoad)
    return () => {
      window.removeEventListener('load', handleLoad)
    }
}, [])

return (...some code)
}

组件能够弄清楚我如何在组件已经期望道具的组件中传递此模拟功能,并且由于Typescript我无法传递其他所需道具的其他任何内容,这是我的测试用例,

it('Should run handleLoad function onMount', ()=>{
    jest.spyOn(React, 'useEffect').mockImplementation(f => f())
    const handleLoad = jest.fn();
    wrapper = mount(<RatingsAndReviews {...propObj} />)
    expect(handleLoad).toHaveBeenCalled();
})

我正在遇到此错误 期望(jest.fn())。tohavebeencalled()

Expected number of calls: >= 1
Received number of calls:    0

I am testing my components using jest and enzyme. I want to load my component when the whole page is loaded so I am using load event inside useEffect, here is my code

const RatingsAndReviews = (props: RatingsAndReviewsProps) => {

const [pageLoaded, setPageLoaded] = useState<boolean>(false)

const handleLoad = () => {
    if (document.readyState === 'complete') {
      setTimeout(() => {
        setPageLoaded(true)
      }, 1500)
    }
}

React.useEffect(() => {
    window.addEventListener('load', handleLoad)
    return () => {
      window.removeEventListener('load', handleLoad)
    }
}, [])

return (...some code)
}

I want to test this handleLoad function but I am not able to figure it out how I can pass this mock function in my component as the component already expect props and as it is TypeScript I can't pass anything else other that the required props, here is my test case

it('Should run handleLoad function onMount', ()=>{
    jest.spyOn(React, 'useEffect').mockImplementation(f => f())
    const handleLoad = jest.fn();
    wrapper = mount(<RatingsAndReviews {...propObj} />)
    expect(handleLoad).toHaveBeenCalled();
})

I am getting this error
expect(jest.fn()).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls:    0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

裂开嘴轻声笑有多痛 2025-01-30 02:16:28

尽量不要模拟第三方库功能的实现,因为错误的模拟实现将破坏其功能。例如,useffect(effect) react Hook不仅执行效果函数。考虑,

React Defers运行useffect直到浏览器绘制后。

你如何嘲笑它?不正确的嘲笑将导致意外的行为。您的测试可能会基于错误的模拟实现来通过,但是当代码实际运行时,该代码将失败。这就是为什么您最好不要嘲笑第三方库的原因。当然,这不是绝对的。如果第三方库的功能简单且独立,则可以嘲笑它们的功能。

对于React组件,我们应该进行仅测试组件的行为和功能而不是实现的黑框测试。我们应该将组件视为单元,而不是其中的功能。

我们应该测试pageloaded状态更改时呈现的内容。

函数组件中定义的事件处理程序是私有的,您无法从外部(测试代码)访问它们。因此,您无法直接调用它们。相反,您应该通过用户事件触发它们。 加载事件的事件。

例如

index.tsx

import React from 'react';
import { useEffect, useState } from 'react';

export const RatingsAndReviews = (props) => {
  const [pageLoaded, setPageLoaded] = useState<boolean>(false);

  console.log('pageLoaded: ', pageLoaded);
  const handleLoad = () => {
    if (document.readyState === 'complete') {
      setTimeout(() => {
        setPageLoaded(true);
      }, 1500);
    }
  };

  useEffect(() => {
    window.addEventListener('load', handleLoad);
    return () => {
      window.removeEventListener('load', handleLoad);
    };
  }, []);

  return <div>{pageLoaded ? 'loaded' : 'not loaded'}</div>;
};

index.test.tsx

import { mount } from 'enzyme';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { RatingsAndReviews } from '.';

describe('RatingsAndReviews', () => {
  it('Should run handleLoad function onMount', () => {
    jest.useFakeTimers();
    const wrapper = mount(<RatingsAndReviews />);
    window.dispatchEvent(new Event('load'));
    expect(wrapper.text()).toBe('not loaded');
    act(() => {
      jest.advanceTimersByTime(1500);
    });
    expect(wrapper.text()).toBe('loaded');
  });
});

测试结果:

 PASS  stackoverflow/71953030/index.test.tsx (11.883 s)
  RatingsAndReviews
    ✓ Should run handleLoad function onMount (47 ms)

  console.log
    pageLoaded:  false

      at RatingsAndReviews (stackoverflow/71953030/index.tsx:7:11)

  console.log
    pageLoaded:  true

      at RatingsAndReviews (stackoverflow/71953030/index.tsx:7:11)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   93.33 |       75 |      80 |   92.86 |                   
 index.tsx |   93.33 |       75 |      80 |   92.86 | 19                
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        13.575 s, estimated 14 s

软件包版本:

"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"jest": "^26.6.3",

Try not to mock the implementation of the third-party library function, because the incorrect mock implementation will destroy its functionality. For example, useEffect(effect) react hook does not just execute the effect function. Consider,

React defers running useEffect until after the browser has painted.

How do you mock it? Incorrect mocking will lead to unexpected behavior. Your tests may pass based on incorrect mock implementation, but the code will fail when it is actually run. That's why you'd better not mock the third-party library. Of course, this is not absolute. You can mock the functions of the third-party library if they are simple and self-contained.

For the React Component, we should do black-box tests that only test the behavior and functionality of the component, not the implementation. We should treat the component as a unit instead of the function inside it.

We should test what is rendered when the pageLoaded state changes.

The event handlers defined inside the function component are private, you can't access them from the outside(test code). So you can't invoke them directly. Instead, you should trigger them by user event. The load event for your case.

E.g.

index.tsx:

import React from 'react';
import { useEffect, useState } from 'react';

export const RatingsAndReviews = (props) => {
  const [pageLoaded, setPageLoaded] = useState<boolean>(false);

  console.log('pageLoaded: ', pageLoaded);
  const handleLoad = () => {
    if (document.readyState === 'complete') {
      setTimeout(() => {
        setPageLoaded(true);
      }, 1500);
    }
  };

  useEffect(() => {
    window.addEventListener('load', handleLoad);
    return () => {
      window.removeEventListener('load', handleLoad);
    };
  }, []);

  return <div>{pageLoaded ? 'loaded' : 'not loaded'}</div>;
};

index.test.tsx:

import { mount } from 'enzyme';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { RatingsAndReviews } from '.';

describe('RatingsAndReviews', () => {
  it('Should run handleLoad function onMount', () => {
    jest.useFakeTimers();
    const wrapper = mount(<RatingsAndReviews />);
    window.dispatchEvent(new Event('load'));
    expect(wrapper.text()).toBe('not loaded');
    act(() => {
      jest.advanceTimersByTime(1500);
    });
    expect(wrapper.text()).toBe('loaded');
  });
});

Test result:

 PASS  stackoverflow/71953030/index.test.tsx (11.883 s)
  RatingsAndReviews
    ✓ Should run handleLoad function onMount (47 ms)

  console.log
    pageLoaded:  false

      at RatingsAndReviews (stackoverflow/71953030/index.tsx:7:11)

  console.log
    pageLoaded:  true

      at RatingsAndReviews (stackoverflow/71953030/index.tsx:7:11)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   93.33 |       75 |      80 |   92.86 |                   
 index.tsx |   93.33 |       75 |      80 |   92.86 | 19                
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        13.575 s, estimated 14 s

package versions:

"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"jest": "^26.6.3",
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文