Bagaimana memata-matai properti nilai (bukan metode) dengan Jasmine


115

Jasmine spyOnbaik untuk mengubah perilaku metode, tetapi adakah cara untuk mengubah properti nilai (daripada metode) untuk objek? kodenya bisa seperti di bawah ini:

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

Jawaban:


97

Pada Februari 2017, mereka menggabungkan PR yang menambahkan fitur ini, mereka dirilis pada April 2017.

jadi untuk memata-matai getter / setter yang Anda gunakan: di const spy = spyOnProperty(myObj, 'myGetterName', 'get'); mana myObj adalah instance Anda, 'myGetterName' adalah nama yang didefinisikan di kelas Anda sebagai get myGetterName() {}dan parameter ketiga adalah tipe getatau set.

Anda dapat menggunakan pernyataan yang sama yang telah Anda gunakan dengan mata-mata yang dibuat dengan spyOn.

Jadi Anda bisa misalnya:

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.

Berikut baris dalam kode sumber github tempat metode ini tersedia jika Anda tertarik.

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

Menjawab pertanyaan awal, dengan Jasmine 2.6.1, Anda akan:

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

7
Bagaimana saya melakukan ini jika valueAa Observableatau Subject? Saya mendapatkanProperty valueA does not have access type get
Ka Mok

4
Itu mungkin berarti Anda tidak dapat menggunakannya di properti itu. spyOnProperty menggunakan getOwnPropertyDescriptor dan memeriksa apakah tipe akses get | set untuk deskriptor properti itu ada. Kesalahan yang Anda peroleh adalah karena deskriptor properti tidak disetel atau didapat untuk properti yang Anda coba mata-matai. Jasmine melakukan ini: const deskriptor = Object.getOwnPropertyDescriptor ... if (! Deskriptor [accessType]) {// error dilempar}
Juan

Jadi, tidak ada cara untuk memata-matai properti tanpa metode pengambil dan penyetel eksplisit? Memata-matai adalah properti yang digunakan.
Dominik

@Dominik Di sini saya menulis semua hal di balik terpal yang terkait dengan ini dalam artikel yang lebih panjang: medium.com/@juanlizarazo/…
Juan

1
@Mathieu itu bukan pernyataan yang bagus karena itu hanya menegaskan apa yang sudah kita ketahui dari apa yang kita perintahkan untuk dilakukan mata-mata, tapi itu hanya apa yang mereka tanyakan dan potongan kode pertanyaan mereka yang sama ¯_ (ツ) _ / ¯ Intinya dari pertanyaan mereka adalah bagaimana memata-matai sebuah properti dan bukan contoh spesifik mereka.
Juan

12

Adakah alasan mengapa Anda tidak bisa langsung mengubahnya pada objek? Ini bukan seolah-olah javascript memaksakan visibilitas properti pada suatu objek.


1
menggunakan spyOnsecara eksplisit menunjukkan bahwa saya ingin mengejek sesuatu, sementara saya secara langsung mengatur properti secara implisit menunjukkan bahwa saya ingin mengejek sesuatu, dan saya tidak yakin orang lain akan mengerti bahwa saya mengejek sesuatu ketika dia membaca kode. Kasus lainnya adalah saya tidak ingin mengubah perilaku bagian dalam objek, misalnya jika saya mengubah properti panjang untuk sebuah array, array tersebut dipangkas, jadi tiruan akan lebih baik
Shuping

@Shuping, dalam hal ini, Anda tidak akan mengejek. Anda akan tersengat yang tidak apa-apa. Anda akan "mengubah perilaku" hanya di dalam ujian yang Anda coba capai dengan spyOn.
Fabio Milheiro

Mungkin Anda ingin memata-matai prototipe objek runtime untuk memastikan properti akan ada saat runtime. Jasmine spyOngagal dalam ujian jika propertinya tidak ada.
sennett

2
Salah satu contohnya adalah menyetel atau menghapus window.sessionStorage:TypeError: Cannot assign to read only property 'sessionStorage' of object '#<Window>'
Chris Sattinger

2
Tidak selalu mungkin untuk menetapkan ulang properti objek dalam javascript
Renaud

12

Jasmine tidak memiliki fungsi itu, tetapi Anda mungkin dapat meretas sesuatu bersama-sama menggunakan Object.defineProperty.

Anda dapat memfaktorkan ulang kode Anda untuk menggunakan fungsi pengambil, lalu memata-matai pengambil.

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

Ya, itulah yang bisa saya lakukan untuk saat ini.
Shuping

4
untuk melati 2 ini:and.returnValue(1)
jtzero

9

Cara terbaik adalah menggunakan spyOnProperty. Ini mengharapkan 3 parameter dan Anda harus lulus getatau setsebagai parameter ketiga.

Contoh

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

Di sini saya menetapkan getdari clientWidthdari div.nativeElementobjek.


6

Jika Anda menggunakan ES6 (Babel) atau TypeScript, Anda dapat menghentikan properti menggunakan get and set accessors

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

Kemudian dalam pengujian Anda, Anda dapat memeriksa bahwa properti disetel dengan:

stub.valueA = 'foo';

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

Atau, jika getter adalah bagian dari kelas yang diuji, rintisan dapat dimasukkan ke dalam subkelas.
ccprog

6

Cara yang benar untuk melakukan ini adalah dengan memata-matai properti, ini akan memungkinkan Anda untuk mensimulasikan properti pada objek dengan nilai tertentu.

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

1

Misalkan ada metode seperti ini yang perlu diuji. srcProperti gambar kecil perlu diperiksa

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 () di bawah ini menyebabkan "Gambar baru" diberi kode palsu dari pengujian, kode spyOn mengembalikan objek yang hanya memiliki properti src

Karena variabel "hook" dicakup agar terlihat dalam kode palsu di SpyOn dan juga nanti setelah "reportABCEvent" dipanggil

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

Ini untuk Jasmine 1.3 tetapi mungkin bekerja pada 2.0 jika "andCallFake" diubah menjadi nama 2.0


1

Saya menggunakan kendo grid dan karena itu tidak dapat mengubah implementasinya menjadi metode getter tetapi saya ingin menguji sekitar ini (mengejek grid) dan tidak menguji grid itu sendiri. Saya menggunakan objek mata-mata tetapi ini tidak mendukung properti mengejek jadi saya melakukan ini:

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

Agak bertele-tele tapi itu berhasil


0

Saya agak terlambat ke pesta di sini saya tahu tapi,

Anda dapat langsung mengakses objek panggilan, yang dapat memberi Anda variabel untuk setiap panggilan

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

-3

Anda tidak dapat meniru variabel tetapi Anda dapat membuat fungsi pengambil untuknya dan meniru metode itu dalam file spesifikasi Anda.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.