我需要测试一个在浏览器中打开新标签的功能
openStatementsReport(contactIds) {
window.open(`a_url_${contactIds}`);
}
我想模拟窗口的open函数,这样我就可以验证正确的URL是否传递给open函数。
使用Jest,我不知道如何模仿窗口。我尝试使用模拟函数设置window.open但这种方式不起作用。以下是测试用例
it('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]
我该怎么做测试用例?任何建议或提示表示赞赏
答案 0 :(得分:37)
而不是window
使用global
it('correct url is called', () => {
global.open = jest.fn();
statementService.openStatementsReport(111);
expect(global.open).toBeCalled();
});
您也可以尝试
const open = jest.fn()
Object.defineProperty(window, 'open', open);
答案 1 :(得分:7)
在Jest中有两种模拟全局变量的方法:
mockImplementation
方法(最类似于Jest的方式),但是它仅适用于jsdom
提供了一些默认实现的那些变量,window.open
是其中之一: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();
});
window
变量的错误消息,例如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;
});
与其直接使用全局值,不如从另一个文件中导入它更干净,因此使用Jest进行模拟将变得无关紧要。
./ test.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}`);
}
}
答案 2 :(得分:6)
在我的组件中,我需要访问window.location.search
,这是我在玩笑测试中所做的:
Object.defineProperty(global, "window", {
value: {
location: {
search: "test"
}
}
});
如果在不同的测试中窗口属性必须不同,我们可以将窗口模拟放入函数中并使其可写,以覆盖不同的测试:
function mockWindow(search, pathname) {
Object.defineProperty(global, "window", {
value: {
location: {
search,
pathname
}
},
writable: true
});
}
并在每次测试后重置
afterEach(() => {
delete global.window.location;
});
答案 3 :(得分:5)
我找到了一种简单的方法:删除并替换
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
});
});
答案 4 :(得分:4)
我们也可以使用global
setupTests
来定义它
// setupTests.js
global.open = jest.fn()
在实际测试中使用global
调用它:
// yourtest.test.js
it('correct url is called', () => {
statementService.openStatementsReport(111);
expect(global.open).toBeCalled();
});
答案 5 :(得分:3)
你可以试试这个:
import * as _Window from "jsdom/lib/jsdom/browser/Window";
window.open = jest.fn().mockImplementationOnce(() => {
return new _Window({ parsingMode: "html" });
});
it("correct url is called", () => {
statementService.openStatementsReport(111);
expect(window.open).toHaveBeenCalled();
});
答案 6 :(得分:3)
我直接将svm->predict(sample, pred, cv::ml::StatModel::RAW_OUTPUT);
分配给jest.fn()
。
window.open
答案 7 :(得分:2)
如果它与https://github.com/facebook/jest/issues/890中的窗口位置问题相似,则可以尝试[调整后]
delete global.window.open;
global.window = Object.create(window);
global.window.open = jest.fn();
答案 8 :(得分:1)
可以测试一下:
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')
})
})
答案 9 :(得分:0)
在有趣的配置中添加setupFilesAfterEnv:[“ ./setupTests.js”],创建该文件并添加要在测试之前运行的代码
//setupTests.js
window.crypto = {
.....
};
参考:https://jestjs.io/docs/en/configuration#setupfilesafterenv-array
答案 10 :(得分:0)
一种对我有用的方法如下。这种方法使我能够测试一些在浏览器和Node中都可以使用的代码,因为它使我可以将window
设置为undefined
。
这是Jest 24.8(我相信):
let windowSpy;
beforeEach(() => {
windowSpy = jest.spyOn(global, 'window', 'get');
});
afterEach(() => {
windowSpy.mockRestore();
});
it('should return https://example.com', () => {
windowSpy.mockImplementation(() => ({
location: {
origin: 'https://example.com'
}
}));
expect(window.location.origin).toEqual('https://example.com');
});
it('should be undefined.', () => {
windowSpy.mockImplementation(() => undefined);
expect(window).toBeUndefined();
});