>  기사  >  웹 프론트엔드  >  Node.js_node.js의 종속성 주입을 사용한 관련 문제 및 솔루션에 대한 간략한 분석

Node.js_node.js의 종속성 주입을 사용한 관련 문제 및 솔루션에 대한 간략한 분석

WBOY
WBOY원래의
2016-05-16 15:53:171219검색

최근에는 코드를 쉽게 분리하고 테스트하는 방법을 이해하기 위해 종속성 주입을 사용하게 되었습니다. 하지만 Node.js의 모듈은 Node에서 제공하는 시스템 API에 의존하기 때문에 프라이빗 종속성이 적절하게 사용되는지 판단하기 어렵습니다. 이 경우 일반적인 종속성 주입은 사용하기 어렵지만 아직 희망을 포기하지 마십시오.

require로 인해 문제가 발생함

Node.js는 필요에 따라 종속성을 쉽게 가져올 수 있습니다. 매우 잘 작동하며 RequireJS와 같은 AMD 스키마 로더보다 간단합니다. 문제는 이러한 종속성을 조롱할 때 발생합니다. Node.js에서 모델 로딩이 제어된다면 테스트 중에 사용되는 의사 객체를 어떻게 제어할 수 있습니까? Node의 vm 모드를 사용할 수 있으며, vm을 통해 새로운 컨텍스트에서 모델을 로드할 수 있습니다. 새로운 컨텍스트에서 실행하면 요구 사항이 모델의 메서드에 반영되는 방식을 제어할 수 있습니다.

솔루션

이 기사 덕분에 이제 꽤 좋은 솔루션을 제공할 수 있습니다.

var vm = require('vm');
var fs = require('fs');
var path = require('path');
 
/**
* Helper for unit testing:
* – load module with mocked dependencies
* – allow accessing private state of the module
*
* @param {string} filePath Absolute path to module (file to load)
* @param {Object=} mocks Hash of mocked dependencies
*/
exports.loadModule = function(filePath, mocks) {
mocks = mocks || {};
 
// this is necessary to allow relative path modules within loaded file
// i.e. requiring ./some inside file /a/b.js needs to be resolved to /a/some
var resolveModule = function(module) {
  if (module.charAt(0) !== '.') return module;
  return path.resolve(path.dirname(filePath), module);
};
 
var exports = {};
var context = {
  require: function(name) {
  return mocks[name] || require(resolveModule(name));
  },
  console: console,
  exports: exports,
  module: {
  exports: exports
  }
};
 
vm.runInNewContext(fs.readFileSync(filePath), context);
return context;
};

여기에서 코드 조각을 다운로드할 수도 있습니다. 비록 코드가 기사에 가장 많이 게시되지는 않았지만 여전히 약간의 설명이 필요할 수 있습니다. 테스트할 때 이 모듈을 테스트에 로드하려고 합니다. , require 대신 loadModule 함수 로드 모듈 테스트를 사용합니다.

첫 번째 매개변수인 filePath는 모델을 테스트하려는 검색 위치를 지정합니다. 두 번째 매개변수인 mocks에는 우리가 요구하려는 모델의 이름과 일치하는 속성 이름을 가진 객체가 포함되어 있습니다. 해당 속성으로 지정되는 값은 일반적으로 필요한 모델을 대체하는 데 사용되는 의사 개체입니다.

기본적으로 vm을 사용하여 다른 "컨텍스트"에서 모델을 로드하고 실행합니다. 즉, 전역 변수(예: 요구 및 내보내기)를 제어할 수 있도록 다시 만듭니다. 사용 가능한 새로운 require 함수를 작성했습니다. 그것이 하는 일은 실행 이름에 대한 모의 종속성이 있는지 확인하는 것뿐입니다. 그렇다면 일반적인 require 함수에 이를 위임합니다.

모듈 로더 사용 예시

아직도 약간 혼란스러우면 아래 코드 예제를 보고 맥락에서 어떻게 사용되는지 확인하면 더 명확해질 수 있습니다. 먼저 간단한 모듈을 만듭니다.

var fs = require('fs');
 
module.exports = {
// Do something with `fs`
}
想象一下这个很酷,对吗?不管怎样,现在我们测试那个模块,但是我们要模拟fs来看看它是怎么在内部使用的。
 
// Jasmine's syntax http://pivotal.github.com/jasmine/
describe('someModule', function() {
var loadModule = require('module-loader').loadModule;
var module, fsMock;
 
beforeEach(function() {
fsMock = {
 // a mock for `fs`
};
 
// load the module with mock fs instead of real fs
module = loadModule('./web-server.js', {fs: fsMock});
});
 
it('should work', function() {
// a test that utilizes the fact that we can now control `fs`
});
});

주목해야 할 중요한 점은 7~12행에서 fs에 대한 더미 객체를 생성하고 새로운 loadModule 함수를 사용하여 이 사용된 객체를 위의 작은 모듈에 연결한다는 것입니다. 오른쪽?).

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.