首页 > 解决方案 > 为什么 Jest 给出 ReferenceError 的?

问题描述

问题

谁能弄清楚,为什么我会收到这个错误?:

● Test suite failed to run

  ReferenceError: Cannot access 'mockResponseData' before initialization

  > 1 | const axios = require('axios');
      |               ^

这是一个在线版本。https://repl.it/@SandraSchlichti/jest-playground-2#getStatusCode.test.js

getStatusCode.test.js

const axios = require('axios');
const getStatusCode = require('./getStatusCode');

const mockResponseData = {
  status: 301,
  statusText: 'Moved Permanently',
  headers: {
    location: 'https://www.google.com/',
    'content-type': 'text/html; charset=UTF-8',
    date: 'Thu, 12 Nov 2020 10:09:41 GMT',
    expires: 'Sat, 12 Dec 2020 10:09:41 GMT',
    'cache-control': 'public, max-age=2592000',
    server: 'gws',
    'content-length': '220',
    'x-xss-protection': '0',
    'x-frame-options': 'SAMEORIGIN',
    'alt-svc': 'h3-Q050=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',
    connection: 'close'
  }
};

// whenever Axios is called from getStatusCode() it won't make a network
// connection, but return the following instead
jest.mock("axios", () => {
  return {
    get: jest.fn().mockResolvedValue({
      data: mockResponseData
    })
  };
});

describe("test getStatusCode ", () => {
  // pretend to get data from the network connection
  let response;
  beforeAll(async () => {
    response = await getStatusCode({
      url: 'https://google.com',
      statusCode: 200,
      timeout: 1000,
      maxRedirects: 0
    });
  });

  // compare returned data with expected
  it("fetches raw response but we are only interested in the statuscode", async () => {
    // ensure the mocked Axios function has been called
    expect(axios.get).toHaveBeenCalled();
  });

  describe('return value', () => {
    it('should be greater than or equal to zero', () => {
      expect(response).toBeGreaterThanOrEqual(0)
    })

      describe('have mocked axios.get() returned data.status', () => {
        it('should have returned 301', async () => {
          expect(await axios.get.mock.results[0].value).toHaveProperty('data.status', 301)
        })
      })
    })

    describe('axios returning rejected promise', () => {
      beforeAll(() => {
        // returning transformed mock
        axios.get.mockRejectedValue({
          data: mockResponseData
        });
      });

    describe('called with arguments', () => {
      let response;
      beforeAll(async () => {
        response = await getStatusCode({
          url: 'https://google.com',
          statusCode: 200,
          timeout: 1000,
          maxRedirects: 0
        });
      });

      it('should return -1', async () => {
        expect(await response.toEqual(-1));
      });
    });
  });

});

getStatusCode.js

const axios = require('axios');
const qs = require('qs');

module.exports = async (options) => {
  options              = options || {};
  options.url          = options.url || {};
  options.statusCode   = options.statusCode || 0;
  options.timeout      = options.timeout || 1000;
  options.maxRedirects = options.maxRedirects || 0;

  try {
    const response = await axios.get(options.url, {
      timeout: options.timeout,
      maxRedirects: options.maxRedirects,
      // make all http status codes a success
      validateStatus: function (status) {
        return true;
      }
  });

    console.log(response);


    return (response.status === options.statusCode) ? 1 : 0;
  } catch (error) {
    return -1;
  }
};

标签: javascriptnode.jsecmascript-6jestjs

解决方案


Jest 将所有调用提升到jest.mock作用域的顶部(在文档中的少数地方提到)。尽管还提到了前缀为的变量mock显然也将被提升,但它们明显低于 jest.mock 调用,导致此错误发生。

我可以建议你使用 jest 的自动模拟功能

import axios from 'axios';

jest.mock('axios')

// and then you'll be able to mock it's return value
axios.get.mockResolvedValue({
  data: mockResponseData
})

它将包含该模块,并将为其每个方法生成一个模拟函数。它最大的好处是,每当删除库方法时,jest 都不会为其生成模拟函数,并且您的测试将失败。

repl.it 示例


推荐阅读