我需要测试一个在浏览器中打开一个新选项卡的功能

openStatementsReport(contactIds) {
  window.open(`a_url_${contactIds}`);
}

我想模拟窗口的打开函数,这样我就可以验证正确的URL被传递给打开函数。

使用笑话,我不知道如何模拟窗口。我试着设置窗口。使用mock函数打开,但这种方式不起作用。下面是测试用例:

it('the correct URL is called', () => {
  window.open = jest.fn();
  statementService.openStatementsReport(111);
  expect(window.open).toBeCalled();
});

但是它给出了误差

expect(jest.fn())[.not].toBeCalled()

jest.fn() value must be a mock function or spy.
    Received:
      function: [Function anonymous]

我应该对测试用例做什么?


当前回答

你可以测试它:

describe('TableItem Components', () => {
    let open_url = ""
    const { open } = window;
    beforeAll(() => {
        delete window.open;
        window.open = (url) => { open_url = url };
    });
    afterAll(() => {
        window.open = open;
    });
    test('string type', async () => {
        wrapper.vm.openNewTab('http://example.com')
        expect(open_url).toBe('http://example.com')
    })
})

其他回答

在Jest配置中,添加setupFilesAfterEnv: ["./setupTests.js"],创建该文件,并添加您想要在测试之前运行的代码:

// setupTests.js
window.crypto = {
   .....
};

参考:setupFilesAfterEnv [array]

试一试:

let windowOpenSpy: jest.SpyInstance;
beforeEach(() => {
    windowOpenSpy = jest.spyOn(window, 'open');
});

it('should open window with dashboard url', () => {
    expect(windowOpenSpy).toBeCalledWith('your URL', '_blank');
});

我找到了一个简单的方法:删除和替换

describe('Test case', () => {
  const { open } = window;

  beforeAll(() => {
    // Delete the existing
    delete window.open;
    // Replace with the custom value
    window.open = jest.fn();
    // Works for `location` too, eg:
    // window.location = { origin: 'http://localhost:3100' };
  });

  afterAll(() => {
    // Restore original
    window.open = open;
  });

  it('correct url is called', () => {
    statementService.openStatementsReport(111);
    expect(window.open).toBeCalled(); // Happy happy, joy joy
  });
});

我直接将jest.fn()赋值给window.open。

window.open = jest.fn()
// ...code
expect(window.open).toHaveBeenCalledTimes(1)
expect(window.open).toHaveBeenCalledWith('/new-tab','_blank')

在Jest中有几种方法可以模拟全局变量:

Use the mockImplementation approach (the most Jest-like way), but it will work only for those variables which has some default implementation provided by jsdom. window.open is one of them: test('it works', () => { // Setup const mockedOpen = jest.fn(); // Without making a copy, you will have a circular dependency problem const originalWindow = { ...window }; const windowSpy = jest.spyOn(global, "window", "get"); windowSpy.mockImplementation(() => ({ ...originalWindow, // In case you need other window properties to be in place open: mockedOpen })); // Tests statementService.openStatementsReport(111) expect(mockedOpen).toBeCalled(); // Cleanup windowSpy.mockRestore(); }); Assign the value directly to the global property. It is the most straightforward, but it may trigger error messages for some window variables, e.g. window.href. test('it works', () => { // Setup const mockedOpen = jest.fn(); const originalOpen = window.open; window.open = mockedOpen; // Tests statementService.openStatementsReport(111) expect(mockedOpen).toBeCalled(); // Cleanup window.open = originalOpen; }); Don't use globals directly (requires a bit of refactoring) Instead of using the global value directly, it might be cleaner to import it from another file, so mocking will became trivial with Jest.

文件。/ . js

jest.mock('./fileWithGlobalValueExported.js');
import { windowOpen } from './fileWithGlobalValueExported.js';
import { statementService } from './testedFile.js';

// Tests
test('it works', () => {
  statementService.openStatementsReport(111)
  expect(windowOpen).toBeCalled();
});

文件。/ fileWithGlobalValueExported.js

export const windowOpen = window.open;

文件。/ testedFile.js

import { windowOpen } from './fileWithGlobalValueExported.js';
export const statementService = {
  openStatementsReport(contactIds) {
    windowOpen(`a_url_${contactIds}`);
  }
}