【问题标题】:Why do Jest give ReferenceError's?为什么 Jest 会给出 ReferenceError?
【发布时间】:2023-03-03 20:52:01
【问题描述】:

问题

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

● 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;
  }
};

【问题讨论】:

    标签: javascript node.js ecmascript-6 jestjs


    【解决方案1】:

    Jest 将所有调用提升到作用域顶部的 jest.mock (it's mentioned in few places in the documentation)。尽管还提到了以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 example

    【讨论】:

    • 我可以问一个额外的问题吗? =) 鉴于我在第 36 行有 statusCode: 200,所以我的 getStatusCode() 应该返回 0,它确实如此。 getStatusCode() 也可以返回 1 如果 ``statusCode: 301`。如何添加此场景?
    • @SandraSchlichting 当然,总是喜欢问好问题 :) 你可以做类似this
    • 这种新方式看起来很干净,但我不明白为什么从第 7-22 行开始的块会给出-1mockResponseData 没有status: 301,这里axios.get.mockRejectedValue() 也有status: 301。所以它应该根据getStatusCode()返回1
    • 我想更好的方法是问:只有在第 48 行你有 statusCode 作为输入参数。第 17 行和第 32 行的输入 statusCode 使用什么?
    • 我尝试创建一个chat,但显然它没有发送通知
    猜你喜欢
    • 2021-03-29
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2011-04-22
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    相关资源
    最近更新 更多