คำตอบนี้จะขึ้นอยู่กับคำตอบของแอนเดรีKöberle
มันไม่ใช่เรื่องง่ายสำหรับฉันที่จะปรับใช้และทำความเข้าใจโซลูชันของเขาดังนั้นฉันจะอธิบายรายละเอียดเพิ่มเติมเล็กน้อยว่ามันทำงานอย่างไรและข้อผิดพลาดบางอย่างที่ควรหลีกเลี่ยงหวังว่ามันจะช่วยผู้เยี่ยมชมในอนาคตได้
ก่อนอื่นการตั้งค่า:
ฉันใช้Karmaเป็นนักวิ่งทดสอบและMochaJsเป็นกรอบการทดสอบ
การใช้บางอย่างเช่นSquireไม่ได้ผลสำหรับฉันด้วยเหตุผลบางประการเมื่อฉันใช้มันกรอบการทดสอบทำให้เกิดข้อผิดพลาด:
TypeError: ไม่สามารถอ่านคุณสมบัติ 'call' ของ undefined
RequireJsมีความเป็นไปได้ในการแมปรหัสโมดูลกับรหัสโมดูลอื่น ๆ นอกจากนี้ยังช่วยในการสร้าง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
ซึ่งใช้งานได้ดี
การใช้
ที่จะใช้มันจำเป็นต้องใช้ในการทดสอบของคุณสร้าง mocks 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
ฟังก์ชัน มีตัวเลือกที่แตกต่างกันเล็กน้อย ฉันจะโพสต์คำตอบโดยหวังว่าจะเป็นประโยชน์