【问题标题】:Mocking simple internal function using Jest for use in rendered React component使用 Jest 模拟简单的内部函数以用于渲染的 React 组件
【发布时间】:2020-02-01 04:26:30
【问题描述】:

我有一个简单的 React 应用程序,其中包含以下 App.js、App.test.js 和 utils.js 文件:

App.js

import React from 'react';
import { randomNameGenerator } from './utils.js';
import './App.css';

function App() {
  return (
    <div>
      {randomNameGenerator()}
    </div>
  );
}

export default App;

App.test.js

import React from 'react';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect'
import App from './App';

it('allows Jest method mocking', () => {
  const { getByText } = render(<App />);
  expect(getByText("Craig")).toBeInTheDocument()
});

utils.js

export function randomNameGenerator() {
    return Math.floor((Math.random() * 2) + 1) == 1 ? 'Steve' : 'Bill';
}

这是一个简单的示例,但我试图完成的是 randomNameGenerator() 函数的 Jest 模拟,只为该特定的 Jest 测试返回 "Craig"强>.

我遵循了各种各样的教程/指南,但找不到任何有用的东西 - 我得到的最接近的(通过“感觉”)是这个(在 App.test.js 中),它没有任何效果:

jest.doMock('./utils', () => {
  const originalUtils = jest.requireActual('./utils');
  return {
    __esModule: true,
    ...originalUtils,
    randomNameGenerator: jest.fn(() => {
      console.log('## Returning mocked typing duration!');
      return 'Craig';
    }),
  };
})

失败的方式在意料之中:

Unable to find an element with the text: Craig. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

    <body>
      <div>
        <div>
          Steve
        </div>
      </div>
    </body>

       6 | it('allows Jest method mocking', () => {
       7 |   const { getByText } = render(<App />);
    >  8 |   expect(getByText("Craig")).toBeInTheDocument()
         |          ^
       9 | });

【问题讨论】:

    标签: javascript reactjs unit-testing mocking jestjs


    【解决方案1】:

    您可以通过调用jest.mock 模拟模块,然后导入它,然后在您的测试中调用mockImplementation 来设置正确的返回值。

    import React from 'react';
    import { render } from '@testing-library/react';
    import '@testing-library/jest-dom/extend-expect'
    import App from './App';
    
    import { randomNameGenerator } from "./utils";
    
    jest.mock('./utils.js', () => ({ 
      randomNameGenerator: jest.fn()
    }));
    
    describe('test', () => {
      it('allows Jest method mocking 1', () => {
        randomNameGenerator.mockImplementation(() => "Craig");
        const { getByText } = render(<App />);
        expect(getByText("Craig")).toBeInTheDocument()
      });
    
      it('allows Jest method mocking 2', () => {
        randomNameGenerator.mockImplementation(() => "Not Craig");
        const { getByText } = render(<App />);
        expect(getByText("Not Craig")).toBeInTheDocument()
      });
    });
    

    【讨论】:

    • 谢谢,这似乎最有效,但有一点需要注意。它需要 每个 测试方法来提供 randomNameGenerator 方法的模拟实现 - 在未定义模拟的情况下,没有“默认”回退到原始实现。我尝试使用requireActual 在jest.mock() 中进行设置,但遇到了范围访问问题(not allowed to reference any out-of-scope variables)
    • 是的,很遗憾看起来没有任何官方方法可以做到这一点,您可能想在 github 上查看:github.com/facebook/jest/issues/2649
    猜你喜欢
    • 2018-01-26
    • 2021-08-27
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多