이 답변은 Andreas Köberle의 답변을 기반으로 합니다.
그의 솔루션을 구현하고 이해하는 것은 쉽지 않았으므로 앞으로의 방문자에게 도움이되기를 바라면서 어떻게 작동하는지, 피해야 할 함정을 좀 더 자세히 설명하겠습니다.
그래서, 우선 설정 :
내가 사용 카르마를 테스트 러너와 같은 MochaJs 테스트 프레임 워크로.
Squire 와 같은 것을 사용하면 나에게 효과가 없었습니다. 어떤 이유로 그것을 사용했을 때 테스트 프레임 워크에서 오류가 발생했습니다.
TypeError : 정의되지 않은 'call'속성을 읽을 수 없습니다
RequireJs 는 모듈 ID를 다른 모듈 ID 에 맵핑 할 수 있습니다 . 또한 전역 과 다른 구성 을 사용하는 require
함수 를 만들 수 있습니다 .
이러한 기능은이 솔루션이 작동하는 데 중요합니다.require
다음은 (많은) 주석을 포함한 모의 코드 버전입니다 (이해하기를 바랍니다). 테스트를 쉽게 요구할 수 있도록 모듈 안에 넣었습니다.
define([], function () {
var count = 0;
var requireJsMock= Object.create(null);
requireJsMock.createMockRequire = function (mocks) {
//mocks is an object with the module ids/paths as keys, and the module as value
count++;
var map = {};
//register the mocks with unique names, and create a mapping from the mocked module id to the mock module id
//this will cause RequireJs to load the mock module instead of the real one
for (property in mocks) {
if (mocks.hasOwnProperty(property)) {
var moduleId = property; //the object property is the module id
var module = mocks[property]; //the value is the mock
var stubId = 'stub' + moduleId + count; //create a unique name to register the module
map[moduleId] = stubId; //add to the mapping
//register the mock with the unique id, so that RequireJs can actually call it
define(stubId, function () {
return module;
});
}
}
var defaultContext = requirejs.s.contexts._.config;
var requireMockContext = { baseUrl: defaultContext.baseUrl }; //use the baseUrl of the global RequireJs config, so that it doesn't have to be repeated here
requireMockContext.context = "context_" + count; //use a unique context name, so that the configs dont overlap
//use the mapping for all modules
requireMockContext.map = {
"*": map
};
return require.config(requireMockContext); //create a require function that uses the new config
};
return requireJsMock;
});
가장 큰 함정 그대로 나에게 시간을 비용이 발생 나는의 RequireJs의 설정을 작성했다. 나는 그것을 (깊게) 복사하려고 시도했고 필요한 속성 (컨텍스트 또는 맵과 같은) 만 재정의했습니다. 작동하지 않습니다! 만 복사하면 baseUrl
제대로 작동합니다.
용법
사용하려면 테스트에서 요구하고 모형을 만든 다음에 전달하십시오 createMockRequire
. 예를 들면 다음과 같습니다.
var ModuleMock = function () {
this.method = function () {
methodCalled += 1;
};
};
var mocks = {
"ModuleIdOrPath": ModuleMock
}
var requireMocks = mocker.createMockRequire(mocks);
다음 은 완전한 테스트 파일 의 예입니다 .
define(["chai", "requireJsMock"], function (chai, requireJsMock) {
var expect = chai.expect;
describe("Module", function () {
describe("Method", function () {
it("should work", function () {
return new Promise(function (resolve, reject) {
var handler = { handle: function () { } };
var called = 0;
var moduleBMock = function () {
this.method = function () {
methodCalled += 1;
};
};
var mocks = {
"ModuleBIdOrPath": moduleBMock
}
var requireMocks = requireJsMock.createMockRequire(mocks);
requireMocks(["js/ModuleA"], function (moduleA) {
try {
moduleA.method(); //moduleA should call method of moduleBMock
expect(called).to.equal(1);
resolve();
} catch (e) {
reject(e);
}
});
});
});
});
});
});
define
함수 를 조롱하고 있습니다. 그래도 몇 가지 다른 옵션이 있습니다. 도움이되기를 바랍니다.