Si-*_*i-N 7 javascript node.js sinon chai
我有这个功能:
let removePresentation = function(presentationName, callback) {
let rimraf = require('rimraf');
callback();
callback();
callback();
if(!presentationName || !presentationName.trim()) {
callback();
return;
}
presentationName = presentationName.replace('.zip', '');
rimraf('./presentations/' + presentationName, function(err) {
if(err) {
console.log(err);
}
callback();
});
};
exports.removePresentation = removePresentation;
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用以下方法进行测试:
var chai = require('chai'),
expect = require('chai').expect,
sinonChai = require('sinon-chai'),
sinon = require('sinon'),
mock = require('mock-require');
chai.use(sinonChai);
describe('removePresentation', function() {
var sandbox;
var callback;
var rimrafSpy;
beforeEach(function() {
sandbox = sinon.sandbox.create();
mock('../business/communications_business', {});
rimrafSpy = sinon.spy();
callback = sinon.spy();
mock('rimraf', rimrafSpy);
});
afterEach(function() {
sandbox.restore();
});
it('should call rimraf if presentation name is valid', function(done) {
let RoomStateBusiness = require('../business/roomstate_business');
RoomStateBusiness.removePresentation('name.zip', callback);
expect(rimrafSpy).to.have.been.calledWith('./presentations/name');
expect(callback).to.have.been.called.once;
done();
});
it('should not call rimraf if presentation name is null', function(done) {
let RoomStateBusiness = require('../business/roomstate_business');
RoomStateBusiness.removePresentation(null, callback);
expect(rimrafSpy).not.to.have.been.called;
expect(callback).to.have.been.called.once;
done();
});
it('should not call rimraf if presentation name is whitespace', function(done) {
let RoomStateBusiness = require('../business/roomstate_business');
RoomStateBusiness.removePresentation(' ', callback);
expect(rimrafSpy).not.to.have.been.called;
expect(callback).to.have.been.called.once;
done();
});
it('should not call rimraf if presentation name is empty string', function(done) {
let RoomStateBusiness = require('../business/roomstate_business');
RoomStateBusiness.removePresentation('', callback);
expect(rimrafSpy).not.to.have.been.called;
expect(callback).to.have.been.called.once;
done();
});
});
Run Code Online (Sandbox Code Playgroud)
即使我清楚地多次调用callback()(仅在进行测试时),expect(callback).to.have.been.called.once;始终会断言为true。我已经检查了Chai api,该api希望该调用完全是一次,尽管无论我调用callback()多少次,它都会一直传递。我究竟做错了什么?
没有这样的主张expect(fn).to.have.been.called.once。
根据sinon-chaidocs,只有:
expect(fn).to.have.been.calledexpect(fn).to.have.been.calledOnce这是一个已知的问题,chai为什么只使用getter的断言是一件坏事。Chai允许您编写一段看起来像属性访问(即断言本身并不以函数调用结尾)的代码来断言...无论您要断言什么。这使用属性获取器执行必要的代码。
问题是,如果您输入错误或其他错误,则表达式将简单地求值为undefined(您正在访问的属性不存在)并且不会执行任何断言代码,从而导致测试通过(因为只有当引发异常)。
在您的情况下,有一个断言called,并且很可能返回一个对象。不幸的是,该对象没有assertion once,因此没有代码执行并且测试通过。
您有2种选择:
Proxy支持的Chai 4和Node.js版本(不确定添加代理支持的位置,可能是Node.js 5或6)-chai通过代理对象代理所有属性访问来检查这些问题,以防止这些问题的发生使用有效的断言undefined is not a function错误而失败。我认为,第二个选项是高度首选的,因为毫无疑问,测试用例的正确性。即使在受支持的平台上,仍然可以关闭Chai代理支持。