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

时间:2017-04-19 14:16:17

标签: javascript node.js testing mocking chai

TL;博士

我正在尝试使用 mocha chai chai-spies 快速应用 >再布线即可。

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

我的设置

我有一个名为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 = 'someone@example.com'
    , 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调用间谍的测试失败如下

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

我觉得我做错了什么但我现在卡住了。感谢任何帮助,谢谢

1 个答案:

答案 0 :(得分:4)

最后,我弄清楚问题是什么。来自rewire github页面:

  

限制

     

使用const它不可能重新连接const(参见#79)。这个可以   可能有一天会被代理人解决,但需要进一步研究。

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

更好的解决方案

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

我们可以要求db中的app.js模块作为const,而不是创建间谍并覆盖const变量:

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

我们可以使用rewire getter 方法导入db文件中的app.test.js模块,然后模拟{{1使用我们的间谍的方法(即 mutate saveUser()变量的属性之一;因为JS中的对象是通过引用传递的,所以获取并改变{{1} app.test.js模块中的对象也会改变app.js模块中的同一个对象)

const

最后,我们可以预期变异的db(即我们的间谍)将被称为

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

总而言之,db.saveUserexpect(db.saveUser).to.have.been.called(); 都不会更改,但测试文件现在应如下所示:

db.js