Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/425.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 开玩笑地嘲笑全球人_Javascript_Unit Testing_Dependencies_Jestjs_Babel Jest - Fatal编程技术网

Javascript 开玩笑地嘲笑全球人

Javascript 开玩笑地嘲笑全球人,javascript,unit-testing,dependencies,jestjs,babel-jest,Javascript,Unit Testing,Dependencies,Jestjs,Babel Jest,是否有任何方式可以模拟全局对象,例如navigator,或Image*?我基本上已经放弃了这一点,并将其留给了一系列可模仿的实用工具方法。例如: // Utils.js export isOnline() { return navigator.onLine; } 测试这个微小的函数很简单,但很粗糙,根本不确定。我可以得到75%的路,但这是我能做到的: // Utils.test.js it('knows if it is online', () => { const {

是否有任何方式可以模拟全局对象,例如
navigator
,或
Image
*?我基本上已经放弃了这一点,并将其留给了一系列可模仿的实用工具方法。例如:

// Utils.js
export isOnline() {
    return navigator.onLine;
}
测试这个微小的函数很简单,但很粗糙,根本不确定。我可以得到75%的路,但这是我能做到的:

// Utils.test.js
it('knows if it is online', () => {
    const { isOnline } = require('path/to/Utils');

    expect(() => isOnline()).not.toThrow();
    expect(typeof isOnline()).toBe('boolean');
});
另一方面,如果我不介意这个间接寻址,我现在可以通过以下实用程序访问
navigator

// Foo.js
import { isOnline } from './Utils';

export default class Foo {
    doSomethingOnline() {
        if (!isOnline()) throw new Error('Not online');

        /* More implementation */            
    }
}
…然后像这样进行决定性的测试

// Foo.test.js
it('throws when offline', () => {
    const Utils = require('../services/Utils');
    Utils.isOnline = jest.fn(() => isOnline);

    const Foo = require('../path/to/Foo').default;
    let foo = new Foo();

    // User is offline -- should fail
    let isOnline = false;
    expect(() => foo.doSomethingOnline()).toThrow();

    // User is online -- should be okay
    isOnline = true;
    expect(() => foo.doSomethingOnline()).not.toThrow();
});
在我使用过的所有测试框架中,Jest感觉是最完整的解决方案,但每当我编写笨拙的代码只是为了使其可测试时,我感觉我的测试工具让我失望

这是唯一的解决方案还是我需要重新布线


*不要傻笑<代码>图像非常适合ping远程网络资源。

由于每个测试套件都运行自己的环境,您可以通过覆盖全局来模拟全局。所有全局变量都可以通过
global
命名空间访问:

global.navigator = {
  onLine: true
}

覆盖仅对当前测试有效,不会影响其他测试。这也是处理
Math.random
Date.now
的好方法

请注意,通过对其进行一些更改,您可能不得不像这样模拟全局变量:

Object.defineProperty(globalObject, key, { value, writable: true });

Jest可能在编写接受的答案后发生了更改,但Jest似乎不会在测试后重置全局设置。请参阅附件中的测试用例

据我所知,解决这个问题的唯一方法是使用
afterEach()
afterAll()
来清理分配给
global
的任务

let originalGlobal = global;
afterEach(() => {
  delete global.x;
})

describe('Scope 1', () => {
  it('should assign globals locally', () => {
    global.x = "tomato";
    expect(global.x).toBeTruthy()
  });  
});

describe('Scope 2', () => {
  it('should not remember globals in subsequent test cases', () => {
    expect(global.x).toBeFalsy();
  })
});

如果有人需要用静态属性模拟全局,那么我的示例应该会有所帮助:

  beforeAll(() => {
    global.EventSource = jest.fn(() => ({
      readyState: 0,
      close: jest.fn()
    }))

    global.EventSource.CONNECTING = 0
    global.EventSource.OPEN = 1
    global.EventSource.CLOSED = 2
  })

如果您使用的是
react testing library
,并且使用了该库提供的
cleanup
方法,则一旦文件中的所有测试运行完毕,它将删除该文件中的所有全局声明。这将不会继续进行任何其他测试

例如:

import { cleanup } from 'react-testing-library'

afterEach(cleanup)

global.getSelection = () => {

}

describe('test', () => {
  expect(true).toBeTruthy()
})

正确的方法是使用。这里的其他答案,即使它们工作,也不要考虑清理和污染全局范围。< /P>
//以前
开玩笑
.spyOn(窗口“导航器”、“获取”)
.mockImplementation(()=>{…})
//毕竟
开玩笑。恢复记忆();
如果需要在
window.navigator
上分配和重新分配属性值,则需要:

  • 声明一个非常量变量
  • 从全局/窗口对象返回它
  • 更改原始变量的值(通过引用)
  • 这将防止在尝试重新分配
    window.navigator
    上的值时出错,因为这些值大多是只读的

    let mockUserAgent = "";
    
    beforeAll(() => {
      Object.defineProperty(global.navigator, "userAgent", {
        get() {
          return mockUserAgent;
        },
      });
    });
    
    it("returns the newly set attribute", () => {
      mockUserAgent = "secret-agent";
      expect(window.navigator.userAgent).toEqual("secret-agent");
    });
    

    global
    是否与浏览器中的
    window
    相同?是的,您可以在那里设置内容。但可能并非所有出现在
    窗口中的内容也出现在
    全局中。这就是为什么我不使用
    global.navigator.onLine
    的原因,因为我不确定
    global
    中是否有
    navigator
    对象。请注意,作为一般做法,现在并非所有全局属性都是可覆盖的。有些测试为可写false,将忽略值更改尝试。“覆盖仅对您当前的测试有效,不会影响其他测试。”-是否有记录在案?@JamesPlayer我可以肯定地确认,一个测试中的覆盖将影响其他测试。至少在一个测试套件中。我经历了相同的行为,在每次测试运行后,我的全局变量没有重置。调用
    jest.clearAllMocks()
    afterEach()
    帮助我。。。从'@angular/compiler/src/util'导入{global}我相信这是自
    @testing library/react
    v9.0以来的默认行为,并且在v10.0中删除每个
    功能后的
    清理——您说“一旦文件中的所有测试都运行完毕”,但每次
    之后都使用
    ,这与我所说的相反“属性导航器没有访问类型get”-这应该是哪个版本的Jest工作?