ฉันต้องการที่จะเปลี่ยนการดำเนินงานของการพึ่งพาล้อเลียนในแต่ละวิธีการทดสอบเดียวโดยการขยายจำลองเริ่มต้นพฤติกรรมและการคืนค่ากลับมาในการดำเนินการเดิมเมื่อรันการทดสอบต่อไป
สั้น ๆ นี่คือสิ่งที่ฉันพยายามบรรลุ:
- จำลองการพึ่งพา
- เปลี่ยน / ขยายการใช้งานจำลองในการทดสอบเดียว
- เปลี่ยนกลับเป็นการจำลองแบบเดิมเมื่อดำเนินการทดสอบครั้งต่อไป
ฉันกำลังใช้Jest v21
.
นี่คือลักษณะของการทดสอบ Jest โดยทั่วไป:
__mocks__/myModule.js
const myMockedModule = jest.genMockFromModule('../myModule');
myMockedModule.a = jest.fn(() => true);
myMockedModule.b = jest.fn(() => true);
export default myMockedModule;
__tests__/myTest.js
import myMockedModule from '../myModule';
// Mock myModule
jest.mock('../myModule');
beforeEach(() => {
jest.clearAllMocks();
});
describe('MyTest', () => {
it('should test with default mock', () => {
myMockedModule.a(); // === true
myMockedModule.b(); // === true
});
it('should override myMockedModule.b mock result (and leave the other methods untouched)', () => {
// Extend change mock
myMockedModule.a(); // === true
myMockedModule.b(); // === 'overridden'
// Restore mock to original implementation with no side effects
});
it('should revert back to default myMockedModule mock', () => {
myMockedModule.a(); // === true
myMockedModule.b(); // === true
});
});
นี่คือสิ่งที่ฉันได้ลองทำแล้ว:
1 - mockFn.mockImplementationOnce (fn)
ข้อดี
- เปลี่ยนกลับสู่การใช้งานดั้งเดิมหลังจากการโทรครั้งแรก
ข้อเสีย
- จะหยุดทำงานหากการทดสอบเรียก
b
ใช้หลายครั้ง - จะไม่เปลี่ยนกลับเป็นการใช้งานดั้งเดิมจนกว่า
b
จะไม่มีการเรียกใช้ (รั่วไหลในการทดสอบครั้งต่อไป)
รหัส:
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
myMockedModule.b.mockImplementationOnce(() => 'overridden');
myModule.a(); // === true
myModule.b(); // === 'overridden'
});
2 - jest.doMock (ชื่อโมดูลโรงงานตัวเลือก)
ข้อดี
- ล้อเลียนอีกครั้งอย่างชัดเจนในทุกการทดสอบ
ข้อเสีย
- ไม่สามารถกำหนดการใช้งานจำลองเริ่มต้นสำหรับการทดสอบทั้งหมด
- ไม่สามารถขยายการใช้งานเริ่มต้นเพื่อบังคับให้ประกาศวิธีการจำลองแต่ละวิธีอีกครั้ง
รหัส:
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
jest.doMock('../myModule', () => {
return {
a: jest.fn(() => true,
b: jest.fn(() => 'overridden',
}
});
myModule.a(); // === true
myModule.b(); // === 'overridden'
});
3 - การเยาะเย้ยด้วยตนเองด้วยวิธีการตั้งค่า (ตามที่อธิบายไว้ที่นี่ )
ข้อดี
- ควบคุมผลลัพธ์ที่เยาะเย้ยได้อย่างสมบูรณ์
ข้อเสีย
- รหัสสำเร็จรูปจำนวนมาก
- ยากที่จะรักษาในระยะยาว
รหัส:
__mocks__/myModule.js
const myMockedModule = jest.genMockFromModule('../myModule');
let a = true;
let b = true;
myMockedModule.a = jest.fn(() => a);
myMockedModule.b = jest.fn(() => b);
myMockedModule.__setA = (value) => { a = value };
myMockedModule.__setB = (value) => { b = value };
myMockedModule.__reset = () => {
a = true;
b = true;
};
export default myMockedModule;
__tests__/myTest.js
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
myModule.__setB('overridden');
myModule.a(); // === true
myModule.b(); // === 'overridden'
myModule.__reset();
});
4 - jest.spyOn (object, methodName)
ข้อเสีย
- ฉันไม่สามารถเปลี่ยนกลับ
mockImplementation
ไปเป็นค่าส่งคืนเดิมที่จำลองไว้ได้ดังนั้นจึงส่งผลต่อการทดสอบครั้งต่อไป
รหัส:
beforeEach(() => {
jest.clearAllMocks();
jest.restoreAllMocks();
});
// Mock myModule
jest.mock('../myModule');
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
const spy = jest.spyOn(myMockedModule, 'b').mockImplementation(() => 'overridden');
myMockedModule.a(); // === true
myMockedModule.b(); // === 'overridden'
// How to get back to original mocked value?
});