需要外部模块作为ES6类实例variables

我有一个ES6类,这取决于一些外部模块的工作。 由于这是一个节点应用程序,我使用CommonJS来要求和加载模块。

然而,这种模块加载使得unit testing变得复杂,这并不是什么秘密。 我当然可以通过构造函数dependency injection所有必需的模块,但是这在dynamictypes语言中感觉很麻烦。 我也不喜欢使用像proxyquire这样的库,因为它膨胀了我的testing代码。

所以我想出了将所需模块存储为实例variables的想法。 例如:

const someModule = require('some-module'); class MyClass { constructor() { this.someModule = someModule; } someFunction(value) { return this.someModule.someFunction(value); } } 

这样我就可以使用模块加载器加载依赖关系,并在unit testing中仍然监视/存根/模拟它们。

这被认为是不好的做法,或者你可以看到任何重大的缺点?

这在个案的基础上肯定是可以接受的。 静态或原型someModule属性会更有效率,但另一方面,这将需要在testing中嘲笑后恢复它。

定期这个模式可能会变得很麻烦,在这种情况下,DI容器可能会更方便。 在Node中有很多,例如从Angular DI中提取的injection-js

在最简单的forms中,它可以是一个纯粹的单一容器,它不会自行创build实例,而是将随机令牌下的现有值(模块导出)存储在随机令牌中:

 class Container extends Map { get(key) { if (this.has(key)) { return super.get(key); } else { throw new Error('Unknown dependency token ' + String(key)); } } set(key, val) { if (key == null) { throw new Error('Nully dependency token ' + String(key)); } else if (arguments.length == 1) { super.set(key, key); } else { super.set(key, val); } } } const container = new Container; 

依赖关系可以直接从容器注册和检索:

 const foo = Symbol('foo'); container.set(foo, require('foo')); container.set('bar', require('bar')); container.set(require('baz')); ... const { foo } = require('./common-deps'); class Qux { constructor() { this.foo = container.get(foo); ... } } 

另外,注射器可以包容容器:

 class DI { constructor(container) { this.container = container; } new(Fn) { if (!Array.isArray(Fn.annotation)) { throw new Error(Fn + ' is not annotated'); } return new Fn(...Fn.annotation.map(key => this.container.get(key))); } call(fn) { if (!Array.isArray(fn.annotation)) { throw new Error(fn + ' is not annotated'); } return fn(...fn.annotation.map(key => this.container.get(key))); } } const di = new DI(container); 

并注意注释类和函数中的DI(注释,请参阅此解释 ):

 class Qux { constructor(foo, bar) { this.foo = foo; ... } } Qux.annotation = [foo, 'bar', require('baz')]; quuxFactory.annotation = [require('baz')] function quuxFactory(baz) { ... } const qux = di.new(Qux); const quux = di.call(quuxFactory);