มีวิธีใดที่จะแก้ไขสายลับจัสมินตามข้อโต้แย้ง?


146

ฉันมีฟังก์ชั่นฉันต้องการทดสอบวิธีที่เรียกว่าวิธี API ภายนอกสองครั้งโดยใช้พารามิเตอร์ที่แตกต่างกัน ฉันต้องการจำลอง API ภายนอกนี้ด้วยสายลับจัสมินและคืนสิ่งต่าง ๆ ตามพารามิเตอร์ มีวิธีใดบ้างที่จะทำเช่นนี้ในดอกมะลิ? สิ่งที่ดีที่สุดที่ฉันสามารถทำได้คือแฮ็คที่ใช้และ CallFake:

var functionToTest = function() {
  var userName = externalApi.get('abc');
  var userId = externalApi.get('123');
};


describe('my fn', function() {
  it('gets user name and ID', function() {
    spyOn(externalApi, 'get').andCallFake(function(myParam) {
      if (myParam == 'abc') {
        return 'Jane';
      } else if (myParam == '123') {
        return 98765;
      }
    });
  });
});

คำตอบ:


213

ในจัสมินรุ่น 3.0 ขึ้นไปคุณสามารถใช้ได้ withArgs

describe('my fn', function() {
  it('gets user name and ID', function() {
    spyOn(externalApi, 'get')
      .withArgs('abc').and.returnValue('Jane')
      .withArgs('123').and.returnValue(98765);
  });
});

สำหรับรุ่นจัสมินที่เก่ากว่า 3.0 callFakeเป็นวิธีที่ถูกต้อง แต่คุณสามารถทำให้มันง่ายขึ้นโดยใช้วัตถุเพื่อเก็บค่าส่งคืน

describe('my fn', function() {
  var params = {
    'abc': 'Jane', 
    '123': 98765
  }

  it('gets user name and ID', function() {
    spyOn(externalApi, 'get').and.callFake(function(myParam) {
     return params[myParam]
    });
  });
});

ขึ้นอยู่กับรุ่นของจัสมินไวยากรณ์ต่างกันเล็กน้อย:

  • 1.3.1: .andCallFake(fn)
  • 2.0: .and.callFake(fn)

แหล่งข้อมูล:


11
นี่คือตอนนี้and.callFake- jasmine.github.io/2.2/ … >
Lucy Bain

ฉันต้องคืนสัญญาที่แตกต่างกันดังนั้นการกลับมาจึงแตกต่างกันเล็กน้อย: กลับมา q.when (params [myParam]) ;. มิฉะนั้นนี่เป็นจุดแก้ปัญหาของฉัน ทางออกในฝันของฉันคือเปลี่ยนการโทรแบบ "and.returnValue"
Bill Turner

7
รู้สึกว่าดอกมะลิควรจะมีวิธีที่ดีกว่าในการประกาศเรื่องนี้ กดไลค์spyOn(fake, 'method').withArgs('abc').and.returnValue('Jane')และ spyOn(fake, 'method').withArgs('123').and.returnValue(98765)
jrharshath

@jrharshath .withArgsไม่ทำงานสำหรับฉันในจัสมิน 2.0
hemkaran_raghav

1
.withArgsไม่สามารถใช้งานได้จริง - ฉันหมายความว่าวิธีการดังกล่าวเหมาะสมเมื่อเขียนข้อสอบ
jrharshath

9

คุณสามารถใช้$provideเพื่อสร้างสายลับ และจำลองการใช้and.returnValuesแทนand.returnValueการส่งผ่านข้อมูลที่มีพารามิเตอร์

ตามเอกสารของจัสมิน:โดยการผูกมัดสายลับด้วยการand.returnValuesเรียกไปยังฟังก์ชั่นทั้งหมดจะคืนค่าเฉพาะตามลำดับจนกว่าจะถึงจุดสิ้นสุดของรายการค่าส่งคืน

describe('my fn', () => {
    beforeEach(module($provide => {
        $provide.value('externalApi', jasmine.createSpyObj('externalApi', ['get']));
    }));

        it('get userName and Id', inject((externalApi) => {
            // Given
            externalApi.get.and.returnValues('abc','123');

            // When
            //insert your condition

            // Then
            // insert the expectation                
        }));
});

นี่เป็นคำตอบที่ถูกต้องเนื่องจากการทดสอบควรรู้อย่างแน่ชัดว่าสายลับจะถูกเรียกใช้อย่างไรดังนั้นจึงควรใช้returnValuesเพื่อรองรับการโทรหลายสาย
Schmuli

2
เพียงชี้แจงคำตอบของ akhouri: วิธีนี้ใช้ได้เฉพาะเมื่อ externalApi.get.and.returnValues('abc','123')เรียกว่าภายในitฟังก์ชัน มิฉะนั้นถ้าคุณตั้งค่ารายการค่าอื่นซึ่งจะไม่ทำงานเนื่องจากลำดับที่การทดสอบนั้นไม่สามารถคาดเดาได้ ในความเป็นจริงการทดสอบไม่ควรขึ้นอยู่กับคำสั่งที่พวกเขาจะดำเนินการ
avi.elkharrat

0

ในกรณีของฉันฉันมีส่วนประกอบที่ฉันกำลังทดสอบและใน constructor ของมันมีบริการ config ด้วยวิธีการที่เรียกว่าgetAppConfigValueที่เรียกว่าสองครั้งแต่ละครั้งที่มีอาร์กิวเมนต์ต่างกัน:

constructor(private configSvc: ConfigService) {
  this.configSvc.getAppConfigValue('a_string');
  this.configSvc.getAppConfigValue('another_string');
}

ในสเป็คของฉันฉันให้ ConfigService ใน TestBed ดังนี้:

{
  provide: ConfigService,
  useValue: {
    getAppConfigValue: (key: any): any {
      if (key === 'a_string) {
        return 'a_value';
      } else if (key === 'another_string') {
        return 'another_value';
      }
    }
  } as ConfigService
}

ดังนั้นตราบใดที่ลายเซ็นสำหรับgetAppConfigValueจะเหมือนกับที่ระบุใน ConfigService จริงสิ่งที่ฟังก์ชันทำภายในสามารถแก้ไขได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.