我有一个发出API请求的javascript实用程序文件。它的顶部有两个条件依赖于window.VarA和window.VarB。其中VarA和VarB是我们的软件赋予窗口的变量。如果设置了它们,则将运行条件代码中的代码。由于此文件实际上并未渲染窗口,因此我无法将这些属性设置为任何值,也无法在条件内获取代码覆盖率。
我尝试渲染默认窗口,但这似乎不起作用。我有Jest和酶。
我正在测试的对象中的代码如下所示:
let param = "";
let url = "";
if(window.VarA !== underfined){
param = window.VarA; <<--need coverage here
}
if(window.VarB !== underfined){
url = window.VarB; <<--need coverage here
}
有什么方法可以模拟这些窗口属性以进行测试?
答案 0 :(得分:1)
<!DOCTYPE html>
<html>
<head>
<title>Track your favorite websites</title>
<meta name="author" content="791894" >
<meta name="date" content="2019-03-01T16:33:43-0700" >
<script type="text/javascript" src="partA.js"></script>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Please Complete the Following Registration</h2>
<form id="register" onsubmit="addToArray();return false">
<table>
<tr><td>Enter Your URL Here</td><td><input type="text" id="url" size="25" required="true"></td></tr>
</table>
<input type="submit" value="Submit">
</form>
<h3><span id="showlist"></span></h3>
</body>
</html>
的默认test environment是使用Jest
的类似浏览器的环境,它提供了jsdom
对象。
如果测试环境为window
,则jsdom
对象可以作为window
或window
访问。
在global
上设置变量就像执行以下操作一样容易:
window
棘手的部分是在代码运行之前 设置这些变量。
考虑以下window.VarA = 'foo'; // global.VarA works as well
window.VarB = 'bar'; // global.VarB works as well
模块:
config.js
如果您使用let param = "";
let url = "";
if (window.VarA !== undefined) {
param = window.VarA;
}
if (window.VarB !== undefined) {
url = window.VarB;
}
export const config = {
param,
url
}
,则代码将不会运行,直到需要该模块为止。允许进行如下测试:
require
另一方面,如果您使用test('setting window variables', () => {
window.VarA = 'foo'; // global.VarA works as well
window.VarB = 'bar'; // global.VarB works as well
const { config } = require('./config'); // now require the module
expect(config.param).toBe('foo'); // SUCCESS
expect(config.url).toBe('bar'); // SUCCESS
});
,则变量必须在import
之前 进行定义,测试从imports are hoisted开始运行,并在测试代码运行:
window
因此,如果您使用的是import { config } from './config'; // this runs first
test('setting window variables', () => {
window.VarA = 'foo'; // <= this doesn't affect config
window.VarB = 'bar'; // <= this doesn't affect config
expect(config.param).toBe('foo'); // FAIL
expect(config.url).toBe('bar'); // FAIL
});
,那么在测试开始运行之前,您需要使用类似setupFilesAfterEnv
的方法来设置import
变量:>
window
答案 1 :(得分:1)
Brian Adams的回答很好。作为setupFilesAfterEnv
的替代方案,您还可以在测试主体中动态导入模块:
test('setting window variables', async () => {
window.VarA = 'foo';
window.VarB = 'bar';
const { config } = await import('./config');
expect(config.param).toBe('foo'); // SUCCESS
expect(config.url).toBe('bar'); // SUCCESS
});
请注意,window
变量无法重新分配-进一步的测试仍将首先引用原始分配的值,否则会产生副作用。例如:
test('setting window variables', async () => { ... });
test('setting a different window variable A', async () => {
window.VarA = 'baz';
const { config } = await import('./config');
expect(config.param).toBe('baz'); // FAIL, it's still 'foo'
});
因此,为了避免精神错乱,值得将window
的作业移至beforeAll
或beforeEach
中:
beforeAll(() => {
window.VarA = 'foo';
window.VarB = 'bar';
});
test('setting window variables', async () => {
const { config } = await import('./config');
expect(config.param).toBe('foo');
expect(config.url).toBe('bar');
});