【问题标题】:Jest URL.createObjectURL is not a functionJest URL.createObjectURL 不是一个函数
【发布时间】:2018-10-24 12:26:23
【问题描述】:

我正在开发一个 reactJs 应用程序。我正在使用 jest 来测试我的应用程序。 我想测试一个下载 blob 的函数。

但不幸的是,我收到了这个错误:

URL.createObjectURL 不是函数

我的测试功能:

describe('download', () => {
    const documentIntial = { content: 'aaa' };
    it('msSaveOrOpenBlob should not have been called when navigao is undefined', () => {
      window.navigator.msSaveOrOpenBlob = null;
      download(documentIntial);
      expect(window.navigator.msSaveOrOpenBlob).toHaveBeenCalledTimes(0);
    });
  });

我要测试的功能:

export const download = document => {
  const blob = new Blob([base64ToArrayBuffer(document.content)], {
    type: 'application/pdf',
  });
  if (window.navigator && window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob);
    return;
  }

  const fileURL = URL.createObjectURL(blob);
  window.open(fileURL);
};

【问题讨论】:

标签: javascript reactjs testing blob jestjs


【解决方案1】:

这看起来就像在 Jest 中的 Global 上设置 URL 一样简单。类似的东西

describe('download', () => {
  const documentIntial = { content: 'aaa' };
  global.URL.createObjectURL = jest.fn();
  it('msSaveOrOpenBlob should not have been called when navigao is undefined', () => {
    global.URL.createObjectURL = jest.fn(() => 'details');
window.navigator.msSaveOrOpenBlob = jest.fn(() => 'details');
download(documentIntial);
expect(window.navigator.msSaveOrOpenBlob).toHaveBeenCalledTimes(1);
  });
});

这应该会产生一个测试,您也可以使用它来检查是否调用了 global.URL.createObjectURL。附带说明:您也可能会遇到与 window.open 类似的问题,如果出现这种情况,我建议您也嘲笑一下。

【讨论】:

  • 我有这个结果:expect(jest.fn())[.not].toHaveBeenCalledTimes() jest.fn() 值必须是模拟函数或间谍。收到:未定义
  • 看看我这次实际测试了。您不应该将 msSaveOrOpenBlob 归零。您将需要模拟它以便能够知道它被调用的频率......否则它不会给你一个调用计数。
【解决方案2】:

jsdom,jest 使用的 WHATWG DOM 的 JavaScript 实现还没有实现这个方法。

您可以在他们的github page 上找到open ticket about this exact issue,其中在 cmets 中提供了一些解决方法。但是,如果您需要 blobURL 实际工作,则必须等待此 FR 解决。

在问题的 cmets 中提出的解决方法是为了开玩笑:

function noOp () { }
if (typeof window.URL.createObjectURL === 'undefined') { 
  Object.defineProperty(window.URL, 'createObjectURL', { value: noOp})
}

【讨论】:

    【解决方案3】:

    由于window.URL.createObjectURL(还)在 jest-dom 中不可用,您需要为其提供一个模拟实现。

    不要忘记在每次测试后重置模拟实现。

    describe("your test suite", () => {
      window.URL.createObjectURL = jest.fn();
    
      afterEach(() => {
        window.URL.createObjectURL.mockReset();
      });
    
      it("your test case", () => {
        expect(true).toBeTruthy();
      });
    });
    

    【讨论】:

      【解决方案4】:

      你只需要在你的 setupTest.js 中写这个

      window.URL.createObjectURL = function() {};
      

      【讨论】:

      • 当其他几个选项都不起作用时,这终于对我有用了。
      【解决方案5】:

      仅仅模拟函数 global.URL.createObjectURL 对我不起作用,因为该函数在导入过程中被某些模块使用,我在导入过程中收到错误 Jest URL.createObjectURL is not a function

      相反,它确实有助于创建文件mockJsdom.js

      Object.defineProperty(URL, 'createObjectURL', {
        writable: true,
        value: jest.fn()
      })
      

      然后将此文件作为包含测试的文件中的第一个导入导入

      import './mockJsdom'
      import { MyObjects} from '../../src/lib/mylib'
      
      test('my test', () => {
        // test code
      }
      

      在这里找到:https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom

      【讨论】:

        【解决方案6】:

        jsdom-worker 包恰好提供了这种方法,并添加了对 web 工作者的支持。以下对我有用:

        npm install -D jsdom-worker
        

        然后在package.json中,编辑或添加jest键:

        {
          ...
          "jest": {
            "setupFiles": [
              "jsdom-worker"
            ]
          }
        }
        

        【讨论】:

          【解决方案7】:

          使用 webkitURL.createObjectURL 而不是 URL.createObjectURL 它对我有用

          【讨论】:

            猜你喜欢
            • 2019-03-28
            • 2021-06-08
            • 2020-08-01
            • 1970-01-01
            • 2021-03-11
            • 2022-06-10
            • 1970-01-01
            • 1970-01-01
            • 2019-09-26
            相关资源
            最近更新 更多