javascript - 使用 Sinon 模拟构造函数中设置的类属性

标签 javascript unit-testing mocha.js sinon es6-class

我正在尝试模拟在构造函数内设置为默认值的类属性

class Files {
  constructor(queueNumber = 0) {
    this.queueNumber = queueNumber;
    this.dir = 'JiraResults';
    if (!fs.existsSync(this.dir)) {
      fs.mkdirSync(this.dir);
    }
  }
  ...
}

构造函数根据 dir 属性创建目录和文件,对于测试,我需要另一个目录,因此我不需要移动实际目录来运行测试。

我尝试了很多方法来替换该属性,但所有方法都失败了,并出现了来自Sinon的不同错误。

第一次尝试:

const tempDir = 'JiraResults-TEMP';
let stubDir;

describe('Files', () => {
  before(() => {
    stubDir = sinon.stub(Files.prototype.constructor, 'dir').value(tempDir);
  }
  ...
}

这样我得到错误TypeError: Cannot stub non-existent own property dir

第二次尝试

const tempDir = 'JiraResults-TEMP';
let stubDir;

describe('Files', () => {
  before(() => {
    stubDir = sinon.stub(Files.prototype, 'dir').value(tempDir);
  }
  ...
}

这样我得到错误TypeError: Cannot stub non-existent own property dir

第三次尝试

const tempDir = 'JiraResults-TEMP';
let stubDir;

describe('Files', () => {
  before(() => {
    stubDir = sinon.stub(Files.prototype, 'this').value({
      dir: sinon.stub().returnsThis(tempDir),
    });
  }
  ...
}

这样我得到错误TypeError: Cannot stub non-existent own property this

<小时/>

我也尝试过其他方法,但从未达到更换该属性的地步。

我查看了 Sinon 文档,但没有一个示例似乎适用于构造函数类。

有人能给我一个关于如何替换此属性的有效示例吗?

谢谢。

最佳答案

您可以直接更改 dir 属性的值,以便被测试的方法将使用 stub 的 dir

例如

files.js:

class Files {
  constructor(queueNumber = 0) {
    this.queueNumber = queueNumber;
    this.dir = "JiraResults";
  }

  mkdir() {
    console.log("make dir: ", this.dir);
  }
}

module.exports = Files;

files.test.js:

const Files = require("./files");
const sinon = require("sinon");

describe("Files", () => {
  it("should use stubbed dir", () => {
    sinon.spy(console, "log");
    const instance = new Files();
    instance.dir = "stubbed dir";
    instance.mkdir();
    sinon.assert.calledWith(console.log, "make dir: ", "stubbed dir");
  });
});

单元测试结果:

Files
make dir:  stubbed dir
    ✓ should use stubbed dir


  1 passing (7ms)

---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |      100 |      100 |      100 |      100 |                   |
 files.js      |      100 |      100 |      100 |      100 |                   |
 files.test.js |      100 |      100 |      100 |      100 |                   |
---------------|----------|----------|----------|----------|-------------------|

更新:

我认为这是不可能的。让我们看一下下面的例子:

files.js:

const fs = require("fs");

class Files {
  constructor(queueNumber = 0) {
    this.queueNumber = queueNumber;
    console.log("before: ", this.dir);
    this.dir = "JiraResults";
    console.log("after: ", this.dir);
    if (!fs.existsSync(this.dir)) {
      fs.mkdirSync(this.dir);
    }
  }
}

Files.prototype.dir = "";

module.exports = Files;

files.test.js:

const Files = require("./files");
const sinon = require("sinon");
const fs = require("fs");

describe("Files", () => {
  it("should use stubbed dir to mkdir", () => {
    sinon.stub(fs, "existsSync").returns(false);
    sinon.stub(fs, "mkdirSync");
    sinon.stub(Files.prototype, "dir").value("stubbed dir");
    console.log("stub dir");
    new Files();
    sinon.assert.calledWith(fs.existsSync, "stubbed dir");
    sinon.assert.calledWith(fs.mkdirSync, "stubbed dir");
  });
});

单元测试结果:

  Files
stub dir
before:  stubbed dir
after:  JiraResults
    1) should use stubbed dir to mkdir


  0 passing (13ms)
  1 failing

  1) Files
       should use stubbed dir to mkdir:
     AssertError: expected existsSync to be called with arguments 
JiraResults stubbed dir 
      at Object.fail (node_modules/sinon/lib/sinon/assert.js:106:21)
      at failAssertion (node_modules/sinon/lib/sinon/assert.js:65:16)
      at Object.assert.(anonymous function) [as calledWith] (node_modules/sinon/lib/sinon/assert.js:91:13)
      at Context.it (src/stackoverflow/59303752/files.test.js:1:2345)

在实例化Files类之前,我们可以成功地为属性dir创建一个 stub 。但是在我们实例化Files类之后。它将把“JiraResults”字符串分配给属性dir,这意味着它将把 stub 目录替换为JiraResults

共有三个选项:

  1. 为属性 dir 设置默认值,Files.prototype.dir = 'JiraResults'(但这取决于您的要求。)
  2. dir 作为参数传递给 Files 类的构造函数。
  3. fs 操作提取到类似于原始 anwser 的方法中。

然后,制作单元测试 stub 会更容易。

关于javascript - 使用 Sinon 模拟构造函数中设置的类属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59303752/

相关文章:

javascript - sourceOne.peek 不是函数

javascript - 问 :500 (Internal Server Error) at $http put?

javascript - 从 html 接收的值更改为在 Node.js 中添加 "\u001c"。如何解决?

javascript - ngMock 在预期请求时提示意外请求

c# - 如何使用 TDD 测试没有 args 构造函数和 setter 的外观类?

node.js - 测试 Mocha 中的预期超时

javascript - Mocha等待/异步处理(预期)错误

javascript - 在 Javascript 中将长时间运行的同步函数转换为异步函数

c# - 让数据库连接保持打开状态?

node.js - 如何测试 node.js websocket 服务器?