2012-02-19 25 views
47

Tôi đang sử dụng Jasmine để kiểm tra xem các đối tượng nhất định có được tạo ra hay không và các phương thức được gọi trên chúng.Làm gián điệp một nhà xây dựng bằng cách sử dụng Jasmine

Tôi có một tiện ích jQuery tạo đối tượng lật và gọi phương thức setValue trên chúng. Mã cho flipcounter là ở đây: https://bitbucket.org/cnanney/apple-style-flip-counter/src/13fd00129a41/js/flipcounter.js

các flipcounters được tạo ra sử dụng:

var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500}); 

Tôi muốn thử nghiệm rằng flipcounters được tạo ra và phương pháp setValue được gọi vào chúng. Vấn đề của tôi là làm thế nào để tôi gián điệp trên các đối tượng này ngay cả trước khi chúng được tạo ra? Tôi có làm gián điệp về hàm tạo và trả về các đối tượng giả không? Mã mẫu thực sự hữu ích. Cảm ơn bạn đã giúp đỡ! :)

Cập nhật:

Tôi đã thử làm gián điệp trên flipCounter như thế này:

myStub = jasmine.createSpy('myStub'); 
spyOn(window, 'flipCounter').andReturn(myStub); 

//expectation 
expect(window.flipCounter).toHaveBeenCalled(); 

Sau đó, thử nghiệm cho cuộc gọi setValue bởi flipCounter:

spyOn(myStub, 'setValue'); 

//expectation 
expect(myStub.setValue).toHaveBeenCalled(); 

là người đầu tiên kiểm tra để khởi tạo flipCounter là tốt, nhưng để kiểm tra cuộc gọi setValue, tất cả những gì tôi nhận được là lỗi 'setValue() không tồn tại'. Tôi có làm điều này đúng không? Cảm ơn!

+0

lý do bạn muốn 'gián điệp' trên đó là gì? –

+1

Tôi muốn chắc chắn rằng nó được tạo ra và giá trị thích hợp được thiết lập. – maru

Trả lời

37

flipCounter chỉ là một chức năng khác, ngay cả khi nó cũng xảy ra để xây dựng một đối tượng. Do đó bạn có thể làm:

var cSpy = spyOn(window, 'flipCounter'); 

để có được một gián điệp vào nó, và làm tất cả các loại kiểm tra trên đó hoặc nói:

var cSpy = spyOn(window, 'flipCounter').andCallThrough(); 
var counter = flipCounter('foo', options); 
expect(cSpy).wasCalled(); 

Tuy nhiên, điều này dường như quá mức cần thiết.Nó sẽ là đủ để làm:

var myFlipCounter = new flipCounter("counter", options); 
expect(myFlipCounter).toBeDefined(); 
expect(myFlipCounter.getValue(foo)).toEqual(bar); 
+0

Không theo dõi gián điệp như thế không phải là một ý tưởng hay;) Tôi sẽ sử dụng phương pháp thứ hai mà tôi đã thực hiện ở trên , kiểm tra và gián điệp một cách riêng biệt trên setValue để đảm bảo rằng các công trình quá. – ggozad

+0

Trong mọi trường hợp khi bạn làm spyOn (cửa sổ, 'flipCounter'). VàReturn (myStub); bạn đã thay thế constructor của bạn bằng cái gì đó không làm gì cả. Bạn phải callThrough hoặc nhân rộng constructor trong khi kiểm tra nó. – ggozad

+0

Nếu TẤT CẢ bạn muốn làm là kiểm tra xem setValue đã được gọi, đừng theo dõi hàm tạo. Thay vì gián điệp (và callThrough()) trên setValue. Sau đó bạn có thể kiểm tra xem nó đã được gọi, kiểm tra các đối số của nó, và vẫn có đối tượng. – ggozad

-2

Không biết cách làm điều này bằng cách sử dụng mụ hoa nhài, nhưng nếu bạn muốn mạnh mẽ mocking/spy/stubs tôi khuyên bạn nên sinon.js, hoạt động rất tốt với hoa nhài.

Từ tài liệu:

Một điệp viên kiểm tra là một chức năng ghi lại lập luận, giá trị trả về, giá trị điều này và ném ngoại lệ (nếu có) đối với tất cả các cuộc gọi của nó. Kiểm tra gián điệp có thể là một chức năng ẩn danh hoặc nó có thể bọc một chức năng hiện có.

Mocks (và kỳ vọng giả) là phương pháp giả (như gián điệp) với hành vi được lập trình trước (như sơ khai) cũng như các kỳ vọng được lập trình trước . Một mô hình sẽ thất bại trong thử nghiệm của bạn nếu nó không được sử dụng như mong đợi.

Với sinon.js bạn có thể tạo mô hình của hàm tạo flipCounter trả về một gián điệp khác.

Sau đó xác nhận rằng hàm tạo được gọi bằng hàm constructorMock.calledWithNew() và xác nhận rằng gián điệp được trả về đã được gọi với hàm returnSpy.calledWith (arg1, arg2 ...).

+4

Không cần sử dụng thêm thư viện khi Jasmine có khả năng tích hợp sẵn. Sinon.js rất hữu ích cho những thứ khác mặc dù – sMoZely

3

Sau đây không dựa vào 'cửa sổ'. Cho phép nói điều này là mã bạn muốn kiểm tra -

function startCountingFlips(flipCounter) { 
    var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500}); 
} 

thử nghiệm của bạn có thể -

var initSpy = jasmine.createSpy('initFlipCounter'); 
var flipCounter = function(id, options) { 
    initSpy(id, options); 
} 
startCountingFlips(flipCounter); 
expect(initSpy).toHaveBeenCalledWith("counter", {inc:23, pace:500}); 
4

Bạn phải thực hiện một constructor giả cho rằng flipCounter đặt setValue tài sản cho một chức năng gián điệp. Hãy nói rằng chức năng bạn muốn kiểm tra là:

function flipIt() { 
    var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500}); 
    myFlipCounter.setValue(100); 
} 

đặc tả của bạn sẽ trông như thế này:

describe('flipIt', function() { 
    var setValue; 
    beforeEach(function() { 
    setValue = jasmine.createSpy('setValue'); 
    spyOn(window, 'flipCounter').and.callFake(function() { 
     this.setValue = setValue; 
    }); 
    flipIt(); 
    }); 
    it('should call flipCounter constructor', function() { 
    expect(window.flipCounter) 
     .toHaveBeenCalledWith("counter", {inc: 23, pace: 500}); 
    }); 
    it('should call flipCounter.setValue', function() { 
    expect(setValue).toHaveBeenCalledWith(100); 
    }); 
}); 
10

tôi sẽ đề nghị sử dụng jasmine.createSpyObj() khi bạn muốn chế nhạo đối tượng với tính mà cần phải được gián điệp trên.

myStub = jasmine.createSpyObj('myStub', ['setValue']); 
spyOn(window, 'flipCounter').andReturn(myStub); 

Kiểm tra này tương tác với giao diện flipCounter được mong đợi, không phụ thuộc vào việc triển khai flipCounter.

+1

Tôi thích câu trả lời này hơn câu trả lời của @ ggozad, bởi vì nó giữ các mô-đun bên ngoài được phân lập từ các thử nghiệm và sử dụng một tiện ích hoa nhài được thiết kế đặc biệt cho các đối tượng giống như mô phỏng. –

0

phiên bản của tôi để kiểm tra một constructor là để do thám nguyên mẫu:

spyOn(flipCounter.prototype, 'setValue').and.callThrough(); 
var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500}); 
expect(flipCounter.prototype.setValue).toHaveBeenCalledTimes(1); 
+0

Rất tốt, cảm ơn. Điều này cũng hoạt động hoàn hảo với các đối tượng dựng sẵn như 'XMLHttpRequest' –

+0

Đối với mockup ajax tôi sử dụng cái này: https://jasmine.github.io/2.2/ajax.html – Holger

Các vấn đề liên quan