首页 > 解决方案 > 如何使用 jest 模拟 window.navigator.language

问题描述

我试图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')
})

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

标签: javascriptreactjstestingjestjs

解决方案


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')
})
...

推荐阅读