Jasmine ile bir değer özelliği (yöntem yerine) casusluk nasıl yapılır


115

Jasmine spyOn, bir yöntemin davranışını değiştirmek için iyidir, ancak bir nesnenin bir değer özelliğini (yöntem yerine) değiştirmenin herhangi bir yolu var mı? kod aşağıdaki gibi olabilir:

spyOn(myObj, 'valueA').andReturn(1);
expect(myObj.valueA).toBe(1);

Yanıtlar:


97

Şubat 2017'de, Nisan 2017'de yayınladıkları bu özelliği ekleyerek bir PR birleştirdiler.

bu yüzden kullandığınız alıcılar / ayarlayıcılar hakkında casusluk yapmak için: const spy = spyOnProperty(myObj, 'myGetterName', 'get'); myObj sizin örneğinizdir, 'myGetterName' sınıfınızda tanımlı olanın adıdır get myGetterName() {}ve üçüncü param ise getveya türüdür set.

Oluşturulan casuslarla halihazırda kullandığınız iddiaların aynısını kullanabilirsiniz spyOn.

Yani örneğin şunları yapabilirsiniz:

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.

İşte ilgileniyorsanız bu yöntemin kullanılabileceği github kaynak kodundaki satır.

https://github.com/jasmine/jasmine/blob/7f8f2b5e7a7af70d7f6b629331eb6fe0a7cb9279/src/core/requireInterface.js#L199

Orijinal soruyu yasemin 2.6.1 ile yanıtlayarak, şunları yaparsınız:

const spy = spyOnProperty(myObj, 'valueA', 'get').andReturn(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();

7
valueAA Observableveya ise bunu nasıl yaparım Subject? Ben alıyorumProperty valueA does not have access type get
Ka Mok

4
Bu muhtemelen onu o mülkte kullanamayacağınız anlamına gelir. spyOnProperty getOwnPropertyDescriptor kullanıyor ve bu özellik tanımlayıcısı için erişim türünün get | set olup olmadığını kontrol ediyor. Aldığınız hata, casusluk yapmaya çalıştığınız mülk için özellik tanımlayıcısının ayarlanmaması veya alınmamasıdır. Jasmine bunu yapar: const descriptor = Object.getOwnPropertyDescriptor ... if (! Descriptor [accessType]) {// error is thrown}
Juan

Öyleyse, açık alıcı ve ayarlayıcı yöntemleri olmadan bir özelliği gözetlemenin bir yolu yok mu? Casusluk, kullanılan bir özelliktir.
Dominik

@Dominik Burada, bununla ilgili tüm başlıkların altını
Juan

1
@Mathieu bu iyi bir iddia değil çünkü casusa yapmasını söylediğimiz şeyden zaten bildiklerimizi iddia ediyor, ama bu onların sorduğu şey ve aynı soru kodu pasajı ¯_ (ツ) _ / ¯ Konu soruları, bir mülke nasıl casusluk yapılacağıydı ve spesifik örnekleri değil.
Juan

12

Bunu doğrudan nesnede değiştirememenizin herhangi bir nedeni var mı? Javascript bir nesnede bir özelliğin görünürlüğünü zorunlu kılar gibi değildir.


1
kullanımı spyOnaçık bir şekilde bir şeyle alay etmek istediğimi belirtirken, özelliği doğrudan örtük olarak ayarladığım bir şeyle alay etmek istediğimi belirtir ve başka birinin kodu okurken bir şeyle alay ettiğimi anlayacağından emin değilim. Diğer durum, nesnenin iç davranışını değiştirmek istemememdir, örneğin bir dizinin length özelliğini değiştirirsem, dizi kırpılır, bu nedenle bir taklit daha iyi olur
Shuping

@Shuping, bu durumda alay etmezsin. Kusursuz bir şekilde aniden boğulacaksın. Yalnızca testin içinde "davranışı değiştiriyor olacaksınız", bu da ile başarmaya çalıştığınız şey buydu spyOn.
Fabio Milheiro

Muhtemelen özelliğin çalışma zamanında var olacağından emin olmak için çalışma zamanı nesne prototipini gözetlemek istersiniz. spyOnÖzellik yoksa Jasmine testte başarısız olur.
sennett

2
Bir örnek, window.sessionStorage'ı ayarlamak veya silmektir:TypeError: Cannot assign to read only property 'sessionStorage' of object '#<Window>'
Chris Sattinger

2
JavaScript'te bir nesne özelliğini yeniden atamak her zaman mümkün değildir
Renaud

12

Jasmine bu işleve sahip değil, ancak kullanarak birlikte bir şeyi hackleyebilirsiniz Object.defineProperty.

Alıcı işlevi kullanmak için kodunuzu yeniden düzenleyebilir, ardından alıcıyı gözetleyebilirsiniz.

spyOn(myObj, 'getValueA').andReturn(1);
expect(myObj.getValueA()).toBe(1);

Evet, şimdilik yapabileceğim şey bu.
Shuping

4
yasemin 2 için:and.returnValue(1)
jtzero

9

En iyi yol kullanmaktır spyOnProperty. Bu 3 parametre bekler ve geçmek gerekir getveya setüçüncü bir param olarak.

Misal

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);

Burada kuruyorum getait clientWidthbir div.nativeElementnesne.


6

ES6 (Babel) veya TypeScript kullanıyorsanız get ve set erişimcileri kullanarak özelliği devre dışı bırakabilirsiniz.

export class SomeClassStub {
  getValueA = jasmine.createSpy('getValueA');
  setValueA = jasmine.createSpy('setValueA');
  get valueA() { return this.getValueA(); }
  set valueA(value) { this.setValueA(value); }
}

Daha sonra testinizde mülkün şunlarla ayarlanıp ayarlanmadığını kontrol edebilirsiniz:

stub.valueA = 'foo';

expect(stub.setValueA).toHaveBeenCalledWith('foo');

Veya alıcılar test edilen sınıfın bir parçasıysa, koçanlar bir alt sınıfa enjekte edilebilir.
ccprog

6

Bunu yapmanın doğru yolu, özellik üzerinde casusluk yapmaktır, belirli bir değere sahip bir nesne üzerinde bir özelliği simüle etmenize izin verecektir.

const spy = spyOnProperty(myObj, 'valueA').and.returnValue(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();

1

Bunun gibi test edilmesi gereken bir yöntem olduğunu varsayalım src. Küçük görüntünün özelliğinin kontrol edilmesi gerekiyor

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;
                }

Aşağıdaki spyOn (), "yeni Resmin" testteki sahte kodla beslenmesine neden olur, spyOn kodu yalnızca src özelliğine sahip bir nesne döndürür.

"Kanca" değişkeni, SpyOn'daki sahte kodda ve daha sonra "reportABCEvent" çağrıldıktan sonra görünür olacak şekilde kapsama dahil edildiğinden

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');
    });

Bu yasemin 1.3 içindir, ancak "andCallFake" 2.0 adıyla değiştirilirse 2.0'da da çalışabilir


1

Bir kendo ızgarası kullanıyorum ve bu nedenle uygulamayı bir alıcı yöntemine değiştiremiyorum, ancak bunun etrafında test etmek (ızgarayı alay etmek) ve ızgaranın kendisini test etmek istemiyorum. Bir casus nesnesi kullanıyordum ama bu özellik alay etmeyi desteklemiyor, bu yüzden şunu yapıyorum:

    this.$scope.ticketsGrid = { 
        showColumn: jasmine.createSpy('showColumn'),
        hideColumn: jasmine.createSpy('hideColumn'),
        select: jasmine.createSpy('select'),
        dataItem: jasmine.createSpy('dataItem'),
        _data: []
    } 

Biraz uzun soluklu ama bir zevk veriyor


0

Buradaki partiye biraz geç kaldım biliyorum ama

Doğrudan çağrı nesnesine erişebilirsiniz, bu size her çağrı için değişkenleri verebilir

expect(spy.calls.argsFor(0)[0].value).toBe(expectedValue)

-3

Değişkenle alay edemezsiniz, ancak onun için bir alıcı işlevi oluşturabilir ve bu yöntemle spec dosyanızda alay edebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.