จัสมินspyOn
เป็นสิ่งที่ดีในการเปลี่ยนพฤติกรรมของวิธีการ แต่มีวิธีใดในการเปลี่ยนคุณสมบัติค่า (แทนที่จะเป็นวิธีการ) สำหรับวัตถุหรือไม่? รหัสอาจเป็นดังนี้:
spyOn(myObj, 'valueA').andReturn(1);
expect(myObj.valueA).toBe(1);
จัสมินspyOn
เป็นสิ่งที่ดีในการเปลี่ยนพฤติกรรมของวิธีการ แต่มีวิธีใดในการเปลี่ยนคุณสมบัติค่า (แทนที่จะเป็นวิธีการ) สำหรับวัตถุหรือไม่? รหัสอาจเป็นดังนี้:
spyOn(myObj, 'valueA').andReturn(1);
expect(myObj.valueA).toBe(1);
คำตอบ:
ในเดือนกุมภาพันธ์ 2017 พวกเขาได้รวมการประชาสัมพันธ์เพื่อเพิ่มคุณสมบัตินี้ซึ่งเปิดตัวในเดือนเมษายน 2017
เพื่อสอดแนม getters / setters ที่คุณใช้:
const spy = spyOnProperty(myObj, 'myGetterName', 'get');
โดยที่ myObj เป็นอินสแตนซ์ของคุณ 'myGetterName' คือชื่อที่กำหนดไว้ในคลาสของคุณget myGetterName() {}
และพารามิเตอร์ตัวที่สามคือประเภทget
หรือset
.
spyOn
คุณสามารถใช้ยืนยันเดียวกันกับที่คุณใช้กับสายลับที่สร้างขึ้นด้วย
ตัวอย่างเช่นคุณสามารถ:
const spy = spyOnProperty(myObj, 'myGetterName', 'get'); // to stub and return nothing. Just spy and stub.
const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.returnValue(1); // to stub and return 1 or any value as needed.
const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.callThrough(); // Call the real thing.
นี่คือบรรทัดในซอร์สโค้ด github ที่มีวิธีนี้หากคุณสนใจ
ตอบคำถามเดิมด้วยดอกมะลิ 2.6.1 คุณจะ:
const spy = spyOnProperty(myObj, 'valueA', 'get').andReturn(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();
เหตุผลใดที่คุณไม่สามารถเปลี่ยนมันบนวัตถุได้โดยตรง? ไม่เหมือนกับว่าจาวาสคริปต์บังคับให้มองเห็นคุณสมบัติบนวัตถุ
spyOn
บ่งบอกอย่างชัดเจนว่าฉันต้องการเยาะเย้ยอะไรบางอย่างในขณะที่ฉันตั้งค่าคุณสมบัติโดยตรงโดยปริยายบ่งบอกว่าฉันต้องการล้อเลียนอะไรบางอย่างและฉันไม่แน่ใจว่าคนอื่นจะเข้าใจว่าฉันกำลังล้อเลียนบางสิ่งบางอย่างเมื่อเขากำลังอ่านรหัส อีกกรณีคือฉันไม่ต้องการเปลี่ยนพฤติกรรมภายในของวัตถุเช่นถ้าฉันเปลี่ยนคุณสมบัติความยาวของอาร์เรย์อาร์เรย์จะถูกตัดออกดังนั้นการจำลองจะดีกว่า
spyOn
.
spyOn
ไม่ผ่านการทดสอบหากคุณสมบัติไม่มีอยู่จริง
TypeError: Cannot assign to read only property 'sessionStorage' of object '#<Window>'
จัสมินไม่มีฟังก์ชั่นนั้น แต่คุณอาจแฮ็คบางอย่างร่วมกันได้โดยใช้ Object.defineProperty
แต่คุณอาจจะสามารถที่จะตัดบางสิ่งบางอย่างร่วมกันโดยใช้
คุณสามารถ refactor โค้ดของคุณเพื่อใช้ฟังก์ชัน getter จากนั้นสอดแนมที่ getter
spyOn(myObj, 'getValueA').andReturn(1);
expect(myObj.getValueA()).toBe(1);
and.returnValue(1)
spyOnProperty
วิธีที่ดีที่สุดคือการใช้งาน คาดหวัง 3 พารามิเตอร์และคุณต้องผ่านget
หรือset
เป็นพารามิเตอร์ตัวที่สาม
const div = fixture.debugElement.query(By.css('.ellipsis-overflow'));
// now mock properties
spyOnProperty(div.nativeElement, 'clientWidth', 'get').and.returnValue(1400);
spyOnProperty(div.nativeElement, 'scrollWidth', 'get').and.returnValue(2400);
นี่ฉันกำลังตั้งค่าget
ของclientWidth
ของdiv.nativeElement
วัตถุ
หากคุณใช้ ES6 (Babel) หรือ TypeScript คุณสามารถดึงคุณสมบัติออกโดยใช้ get และ set accessors
export class SomeClassStub {
getValueA = jasmine.createSpy('getValueA');
setValueA = jasmine.createSpy('setValueA');
get valueA() { return this.getValueA(); }
set valueA(value) { this.setValueA(value); }
}
จากนั้นในการทดสอบของคุณคุณสามารถตรวจสอบว่าคุณสมบัติถูกตั้งค่าด้วย:
stub.valueA = 'foo';
expect(stub.setValueA).toHaveBeenCalledWith('foo');
วิธีที่ถูกต้องในการทำเช่นนี้คือการสอดแนมทรัพย์สินซึ่งจะช่วยให้คุณสามารถจำลองคุณสมบัติบนวัตถุที่มีค่าเฉพาะได้
const spy = spyOnProperty(myObj, 'valueA').and.returnValue(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();
สมมติว่ามีวิธีการเช่นนี้ที่ต้องทดสอบsrc
คุณสมบัติของภาพขนาดเล็กจำเป็นต้องตรวจสอบ
function reportABCEvent(cat, type, val) {
var i1 = new Image(1, 1);
var link = getABC('creosote');
link += "&category=" + String(cat);
link += "&event_type=" + String(type);
link += "&event_value=" + String(val);
i1.src = link;
}
spyOn () ด้านล่างทำให้ "รูปภาพใหม่" ถูกป้อนรหัสปลอมจากการทดสอบรหัส spyOn จะส่งคืนวัตถุที่มีคุณสมบัติ src เท่านั้น
เนื่องจากตัวแปร "hook" ถูกกำหนดขอบเขตให้มองเห็นได้ในโค้ดปลอมใน SpyOn และหลังจากนั้น "reportABCEvent" จะถูกเรียกว่า
describe("Alphabetic.ads", function() {
it("ABC events create an image request", function() {
var hook={};
spyOn(window, 'Image').andCallFake( function(x,y) {
hook={ src: {} }
return hook;
}
);
reportABCEvent('testa', 'testb', 'testc');
expect(hook.src).
toEqual('[zubzub]&arg1=testa&arg2=testb&event_value=testc');
});
นี่ใช้สำหรับ Jasmine 1.3 แต่อาจใช้ได้กับ 2.0 ถ้า "andCallFake" ถูกเปลี่ยนเป็นชื่อ 2.0
ฉันใช้กริดเคนโดดังนั้นจึงไม่สามารถเปลี่ยนการใช้งานเป็นวิธี getter ได้ แต่ฉันต้องการทดสอบสิ่งนี้ (เยาะเย้ยกริด) และไม่ได้ทดสอบกริดเอง ฉันใช้วัตถุสอดแนม แต่สิ่งนี้ไม่สนับสนุนการล้อเลียนทรัพย์สินดังนั้นฉันจึงทำสิ่งนี้:
this.$scope.ticketsGrid = {
showColumn: jasmine.createSpy('showColumn'),
hideColumn: jasmine.createSpy('hideColumn'),
select: jasmine.createSpy('select'),
dataItem: jasmine.createSpy('dataItem'),
_data: []
}
ค่อนข้างยืดเยื้อ แต่ใช้ได้ผลดี
ฉันไปงานปาร์ตี้ที่นี่ช้าไปหน่อย แต่ฉันรู้ว่า
คุณสามารถเข้าถึงวัตถุการโทรได้โดยตรงซึ่งสามารถให้ตัวแปรสำหรับการโทรแต่ละครั้ง
expect(spy.calls.argsFor(0)[0].value).toBe(expectedValue)
คุณไม่สามารถเยาะเย้ยตัวแปรได้ แต่คุณสามารถสร้างฟังก์ชัน getter และจำลองวิธีการนั้นในไฟล์ข้อมูลจำเพาะของคุณได้
valueA
เป็นObservable
หรือSubject
? กำลังเดินทางProperty valueA does not have access type get