使用Karma/Mocha/Sinon/Chai进行单元测试window.location.assign

6

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

然而,我完全不明白为什么我会得到以下错误:

TypeError: Cannot redefine property: assign

当我在这个项目上运行npm test时:
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文件。 - zumafra
const stub = sinon.stub(window.location, 'assign'); 中,使用 spy 而不是 stub 怎么样? - Yonggoo Noh
2个回答

5
你看到的问题是因为window.location.assign是一个本地函数,不可写入和不可配置。请参阅MDN上的属性描述符讨论
查看此截图可能会帮助你理解:

Showing property descriptor of window.location.assing

这意味着sinon无法对assign函数进行间谍,因为它无法覆盖其属性描述符。
最简单的解决方案是将所有调用window.location.assign的方法包装到自己的方法中,像这样:
function assignLocation(url) {
  window.location.assign(url);
}

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

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

感谢您的回复。 - zumafra
然后以某种方式测试这个方法是否有效,哈哈。 - Philll_t

0

试试这个:

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

1
这应该是一个被接受的答案。我只是在 sinon.stub(window.location, "assign") 前面加了 Object.defineProperty,测试就通过了。 - Vladislav Sorokin
2
在2021年,当我不幸尝试这个操作时,出现了“TypeError: Cannot redefine property:location”错误。 - Valerie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接