我想对我构建的模块进行单元测试。 给人一种看起来很像的印象.. MyModule的:
function MyModule(...) {
var self = this;
MyModule.init.call(self, ...);
}
util.inherits(MyModule, MySuperModule);
MyModule.init = function(...) {
...
};
MyModule.prototype.logic = function(..., done) {
calls fnA, fnB, fnC, fnD conditionally
done(...)
};
MyModule.prototype.fnA = function(...) {
...
};
MyModule.prototype.fnB = function(...) {
...
};
MyModule.prototype.fnC = function(...) {
...
};
MyModule.prototype.fnD = function(...) {
...
};
MySuperModule:
function MySuperModule(...) {
...
}
MySuperModule.prototype,fn = function(..., done) {
var self = this;
...
self.logic(..., function done(...) {
...
done(...)
});
}
现在MyModule.logic()永远不会被用户显式调用,只调用MySuperModule.fn()。 所有其他MyModule函数也是如此,这些函数根据通过委托链传递的给定参数有条件地调用。
我的问题如下:
答案 0 :(得分:2)
在我看来,你当然应该测试各个功能,无论用户是否直接调用它们。
单元测试的目的是尝试确保测试的各个单元执行他们期望的操作。如果您(相对)确定您的各个功能/单元的行为符合预期,您可以更加确信它们可以很好地相互协作。
很难真正从你的代码片段中收集模块的性质,因此建议如何实现测试很困难。但是,您似乎要问的是如何验证是否调用了done / callback函数以及使用哪些参数。 为此,我建议使用存根。我通常使用sinon,但我确信其他类似工具也可用。
var sinon = require( "sinon" );
var should = require( "chai" ).should();
var yourModule = require( "your-module" );
var doneStub = sinon.stub();
yourModule.yourFunction( ..., doneStub );
doneStub.should.have.been.called;
var args = doneStub.getCall( 0 ).args;
args[ 0 ].should.be.eql( ... );
// etc etc
您还应该考虑使用测试运行器,我喜欢mocha!
答案 1 :(得分:2)
这实际上取决于你如何在MySuperModule上注入MyModule。但首先我要指出,在单元测试中,你必须单独测试MyModule,MySuperModule使用MyModule的Mocked版本和所有其他依赖项。这是因为你不想两次测试MyModule,不需要那样。
因此,为了创建存根,有一个名为Sinon.JS的库可以正常工作。
因此,如果出于任何原因你只想对MyModule进行间谍活动,这意味着你只是将一个监听器附加到MyModule(它应用于MyModule方法),它会计算并告知是否有一个给定的方法被调用以及如何调用。
var MyModuleMethodASpy = sinon.spy(MyModulem 'MethodA');
MySuperModule.someMethod();
assert(MyModuleMethodASpy.called)
因此,此代码创建一个间谍,在MySuperModule上触发一些方法并检查是否曾调用MyModule.MethodA()
。
如果要控制哪些依赖关系返回特定方法,您也可以创建存根,例如:
var MyModuleStub = sinon.stub(MyModule, 'MethodA').returns([...somedata]);
答案 2 :(得分:1)
你应该进行渐进式测试。你应该测试每一个功能。
在这里你怎么做。