如何使用 jest 模拟 window.navigator.language

IT技术 javascript reactjs testing jestjs
2021-05-17 13:23:52

我试图window.navigator.language在我的玩笑单元测试中模拟浏览器中属性,以便我可以测试页面上的内容是否使用正确的语言

我在网上找到了使用这个的人:

Object.defineProperty(window.navigator, 'language', {value: 'es', configurable: true});

我已经将它设置在我的测试文件的顶部,它正在那里工作

但是,当我在单个测试中重新定义时(并且人们设置为确保可配置设置为 true)它不会重新定义它并且只是使用旧值,有没有人知道一种绝对改变它的方法?

beforeEach(() => {
    jest.clearAllMocks()
    Object.defineProperty(global.navigator, 'language', {value: 'es', configurable: true});
    wrapper = shallow(<Component {...props} />)
})

  it('should do thing 1', () => {
      Object.defineProperty(window.navigator, 'language', {value: 'de', configurable: true});
      expect(wrapper.state('currentLanguage')).toEqual('de')
    })

it('should do thing 2', () => {
  Object.defineProperty(window.navigator, 'language', {value: 'pt', configurable: true});
  expect(wrapper.state('currentLanguage')).toEqual('pt')
})

对于这些测试,它不会将语言更改为我设置的新语言,而是始终使用顶部的语言

3个回答

window.navigator并且它的属性是只读的,这就是为什么Object.defineProperty需要设置window.navigator.language. 它应该适用于多次更改属性值。

问题是组件已经在 中实例化beforeEachwindow.navigator.language更改不会影响它。

使用Object.defineProperty了嘲讽性质手动将需要存储原始描述符和还原以及手动。这可以通过jest.spyOn. jest.clearAllMocks()对手动间谍/模拟没有帮助,Jest 间谍可能不需要它。

应该是:

let languageGetter;

beforeEach(() => {
  languageGetter = jest.spyOn(window.navigator, 'language', 'get')
})

it('should do thing 1', () => {
  languageGetter.mockReturnValue('de')
  wrapper = shallow(<Component {...props} />)
  expect(wrapper.state('currentLanguage')).toEqual('de')
})
...

在 Estus Flask 的回答中添加一点,您还可以监视您的安装文件:

在 jest 配置文件中激活 setupFiles 功能:

setupFiles: ['./test/mock-data/globals.js']

然后在 globals.js 中监视 userAgent 或任何其他属性:

global.userAgent = jest.spyOn(navigator, 'userAgent', 'get');

最后在您的测试中模拟返回值:

describe('abc', () => {
  global.userAgent.mockReturnValue(
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4)\
           AppleWebKit/600.1.2 (KHTML, like Gecko)\
           Version/13.0.0 Safari/600.1.2'
  );
  test('123', async () => {
    const result = await fnThatCallsOrUseTheUserAgent();
    expect(result).toEqual('Something');
  });
});

或者

开玩笑的配置文件

setupFiles: ['./test/mock-data/globals.js']

globals.js

const navigator = { language: 'Chalcatongo Mixtec', ...anyOtherPropertiesYouNeed };

Object.defineProperty(window, 'navigator', {
   value: navigator,
   writable: true
});

然后你可以在你的个人测试设置中自由变异