【问题标题】:Unit Testing window.location.assign using Karma/Mocha/Sinon/Chai单元测试 window.location.assign 使用 Karma/Mocha/Sinon/Chai
【发布时间】:2019-02-03 17:29:42
【问题描述】:

我正在尝试使用 Karma 作为我的测试运行器、Mocha 作为我的测试框架、Sinon 作为我的模拟/存根/间谍库以及 Chai 作为我的断言库来对一个函数进行单元测试。我在 Karma 配置中使用 Chromium 作为无头浏览器。

但是,对于为什么会出现以下错误,我完全感到困惑:

TypeError: Cannot redefine property: assign

...当我对此运行 npm 测试时:

function routeToNewPlace() {  
  const newLoc = "/accountcenter/content/ac.html";
  window.location.assign(newLoc);
}
describe('tests', function() {
  before('blah', function() {
    beforeEach('test1', function() {
          window.onbeforeunload = () => '';
      });
    });
  it('routeToNewPlace should route to new place', function() {
    expectedPathname = "/accountcenter/content/ac.html";
    routeToNewPlace();
    const stub = sinon.stub(window.location, 'assign'); 
    assert.equal(true, stub.withArgs(expectedUrl).calledOnce);
    stub.restore();
  });
});

如您所见,我正在尝试为 window.location 分配一个空字符串,但这似乎没有帮助。

这是我的 karma.config.js:

module.exports = function(config) {
    config.set({
      frameworks: ['mocha', 'chai', 'sinon'],
      files: ['jstests/**/*.js'],
      reporters: ['progress'],
      port: 9876,  // karma web server port
      colors: true,
      logLevel: config.LOG_INFO,
      //browsers: ['Chrome', 'ChromeHeadless', 'MyHeadlessChrome'],
      browsers: ['ChromeHeadless'],
      customLaunchers: {
        MyHeadlessChrome: {
          base: 'ChromeHeadless',
          flags: ['--disable-translate', '--disable-extensions', '--remote-debugging-port=9223']
        }
      },
      autoWatch: false,
      // singleRun: false, // Karma captures browsers, runs the tests and exits
      concurrency: Infinity
    })
  }

任何想法将不胜感激。

【问题讨论】:

  • 编辑添加我正在使用 Chromium 无头浏览器,并提供我的 karma.config.js。
  • const stub = sinon.stub(window.location, 'assign'); 中使用spy 代替stub 怎么样?

标签: unit-testing mocha.js karma-runner sinon chai


【解决方案1】:

您看到的问题是window.location.assign 是一个不可写且不可配置的本机函数。见property descriptors on MDN的讨论。

看看这个截图,它可能会帮助你理解:

这意味着 sinon 无法监视 assign 函数,因为它无法覆盖其属性描述符。

最简单的解决方案是将所有对window.location.assign 的调用封装到您自己的方法之一中,如下所示:

function assignLocation(url) {
  window.location.assign(url);
}

然后在你的测试中,你可以这样做:

const stub = sinon.stub(window, 'assignLocation');

【讨论】:

  • 感谢您的回复。
【解决方案2】:

试试这个:

Object.defineProperty(window, 'location', {
    writable: true,
    value: {
        assign: () => {}
    }
});
sinon.spy(window.location, 'assign');

【讨论】:

  • 这应该是一个可以接受的答案。我只是将 Object.defineProperty 放在 sinon.stub(window.location, "assign") 之前,测试通过了。
  • 2021 年,当我伤心地尝试这个时,我得到:TypeError: Cannot redefine property: location
猜你喜欢
  • 2023-04-11
  • 2018-11-05
  • 2016-05-26
  • 2021-09-27
  • 2015-12-01
  • 2018-04-08
  • 2019-02-14
  • 2018-02-13
  • 2023-03-21
相关资源
最近更新 更多