javascript - 如何使用 rewirejs 和 chai-spies 模拟函数来测试它?

标签 javascript node.js testing mocking chai

tl;博士

我正在尝试使用 mochachaichai-spies 测试 express 应用>重新布线

特别是,我想做的是模拟模块中存在的函数并使用 chai spy 。

我的设置

我有一个名为 db.js 的模块,它导出 saveUser() 方法

db.js

module.exports.saveUser = (user) => {
  // saves user to database
};

app.js 模块需要 db 模块

app.js

const db = require('./db');

module.exports.handleSignUp = (email, password) => {
  // create user object
  let user = {
    email: email,
    password: password
  };
  // save user to database
  db.saveUser(user); // <-- I want want to mock this in my test !!
};

最后在我的测试文件 app.test.js 中我有以下内容

app.test.js

const chai = require('chai')
  , spies = require('chai-spies')
  , rewire = require('rewire');

chai.use(spies);
const expect = chai.expect;

// Mock the db.saveUser method within app.js
let app = rewire('./app');
let dbMock = {
  saveUser: chai.spy()
};
app.__set__('db', dbMock);

// Perform the test
it('should call saveUser', () => {
  let email = '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="41322e2c242e2f24012439202c312d246f222e2c" rel="noreferrer noopener nofollow">[email protected]</a>'
    , password = '123456';

  // run the method we want to test
  app.handleSignUp(email, password);

  // assert that the spy is called
  expect(dbMock.saveUser).to.be.spy; // <--- this test passes
  expect(dbMock.saveUser).to.have.been.called(); // <--- this test fails
});

我的问题

我的问题是,我确保 app.handleSignUp 调用 spy 的测试失败,如下

AssertionError: expected { Spy } to have been called at Context.it (spies/app.test.js:25:40)

我感觉我做错了什么,但此刻我陷入困境。感谢任何帮助,谢谢

最佳答案

终于明白问题出在哪里了。来自 rewire github 页面:

Limitations

Using const It's not possible to rewire const (see #79). This can probably be solved with proxies someday but requires further research.

因此,在 app 中将 const db = require('./db'); 更改为 let db = require('./db'); .js 使所有测试通过。

更好的解决方案

但是,由于将所有 const 声明更改为 let 以便使用 spy 测试应用程序非常麻烦,因此以下方法似乎更好:

我们可以像我们一样将 app.js 中的 db 模块作为 const 要求,而不是创建 spy 并覆盖常量变量:

let dbMock = {
  saveUser: chai.spy()
};
app.__set__('db', dbMock);

我们可以使用rewiregetter方法在我们的app.test.js中导入db模块> 文件,然后使用我们的 spy 模拟 saveUser() 方法(即const 变量的属性之一变异;因为对象JS 通过引用传递,获取和修改 app.test.js 模块中的 db 对象也会修改 app.js 模块中的同一对象)

const db = app.__get__('db');
db.saveUser = chai.spy()

最后,我们可以预期变异的db.saveUser(即我们的 spy )将被调用

expect(db.saveUser).to.have.been.called();

总而言之,db.jsapp.js 都不会更改,但测试文件现在应如下所示:

const chai = require('chai')
  , spies = require('chai-spies')
  , rewire = require('rewire');

chai.use(spies);
let expect = chai.expect;

// Fetch the app object
let app = rewire('./app');

// Use the getter to read the const db object and mutate its saveUser property
const db = app.__get__('db');
db.saveUser = chai.spy()

// Finally perform the test using the mocked 
it('should call saveUser', () => {
  let email = '<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2a5945474f45444f6a4f524b475a464f04494547" rel="noreferrer noopener nofollow">[email protected]</a>'
    , password = '123456';

  // run the method we want to test
  app.handleSignUp(email, password);

  expect(db.saveUser).to.have.been.called(); // <--- now passes!!!
});

关于javascript - 如何使用 rewirejs 和 chai-spies 模拟函数来测试它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43498324/

相关文章:

javascript - knockout HTML 绑定(bind)和 HTML 字符串长度

javascript - 如何在浏览器中使用 npm 模块?甚至可以在本地(PC)中使用它们?

node.js - 生产环境动态生成 Express 路由失败

ruby-on-rails - 我可以看看 PhantomJS 中发生了什么吗?

ruby-on-rails - 没有路由匹配 { :action= >"show", :controller= >"users"} 错误

javascript - 如何将数据从一个函数导出到另一个函数

javascript - 使用 jQuery 将事件转发到另一个元素

javascript - 通过 JS 函数打开 JqueryMobile Dialog

node.js - 尝试在 Windows 7 中通过 Electron 连接到 Oracle DB

angularjs - 测试失败,因为 AngularJS 没有及时初始化