2008-11-25 29 views

Trả lời

22

Here's the commit which adds the feature to rspec - Đây là ngày 25 tháng 5 năm 2008. Với điều này bạn có thể làm

A.any_instance.stub(do_something: 23) 

Tuy nhiên, đá quý mới nhất v ersion of rspec (1.1.11, 10/2008) không có bản vá này.

This ticket tuyên bố rằng họ đã rút nó ra vì lý do bảo trì và giải pháp thay thế chưa được cung cấp.

Có vẻ như bạn không thể làm điều đó tại thời điểm này. Bạn sẽ phải hack lớp bằng tay bằng cách sử dụng alias_method hoặc somesuch.

+3

Xuất hiện rằng nó đã được đưa trở lại với 2.6.0 vì vậy nó trong đó bây giờ ... – rogerdpack

+3

@rogerdpack: thực sự, cuối cùng! http://blog.davidchelimsky.net/2011/05/12/rspec-260-is-released/ "Thêm hỗ trợ cho any_instance.stub và any_instance.should_receive" – tokland

+0

Bất kỳ ý tưởng nào nếu bạn muốn đính kèm nội dung nào đó trực tiếp vào trường hợp đó được tạo bằng cách mới, mặc dù? như should_receive (: blah) .exactlY (5) .thời gian --- và bạn không muốn điều đó đối với bất kỳ đối tượng nào, chỉ là một đối tượng cụ thể? – xaxxon

11

Tôi không biết làm thế nào để làm điều đó trong khuôn khổ giả của spec, nhưng bạn có thể dễ dàng trao đổi nó ra cho mocha làm như sau:

# should probably be in spec/spec_helper.rb 
Spec::Runner.configure do |config| 
    config.mock_with :mocha 
end 

describe A, " when initialized" do 
    it "should set x to 42" do 
    A.new.x.should == 42 
    end 
end 

describe A, " when do_something is mocked" do 
    it "should set x to 23" do 
    A.any_instance.expects(:do_something).returns(23) 
    A.new.x.should == 23 
    end 
end 
5

hoặc với RR:

stub.any_instance_of(A).do_something { 23 } 
-1

Trong phiên bản của tôi về rspec (1.2.2) Tôi có thể làm điều này:

A.should_receive(:new).and_return(42) 

Tôi biết nó có lẽ là để muộn để trả lời cho các poster ban đầu, nhưng tôi trả lời nó anyway để tham khảo trong tương lai, như Tôi đến đây với cùng một câu hỏi nhưng tìm ra nó đang làm việc trên phiên bản rspec mới nhất.

+0

Hành vi của đề xuất của bạn không chính xác. Đó là phương thức do_something trả về 42, không phải là initializer. –

0

Để còn sơ khai một phương pháp dụ, bạn có thể làm một cái gì đó như thế này:

before :each do 
    @my_stub = stub("A") 
    @my_stub.should_receive(:do_something).with(no_args()).and_return(42) 
    @my_stub.should_receive(:do_something_else).with(any_args()).and_return(true) 
    A.stub(:new).and_return(my_stub) 
end 

Nhưng khi pschneider chỉ ra, chỉ trả 42 trên mới với: A.stub(:new).and_return(42) hoặc một cái gì đó về việc đó.

+0

Tôi nghĩ rằng vấn đề là để đưa ra phương pháp thể hiện khi bạn không kiểm soát việc tạo ra các cá thể trong bài kiểm tra của bạn. Thêm vào đó, bộ khởi tạo không trả về 42, nó đặt một biến cá thể: đó là phương thức do_something trả về 42 mà cần phải được stubbed. –

+1

'A.stub (: new) .and_return (@my_stub)' sẽ trả về cá thể cá thể mỗi lần, do đó cho phép bạn kiểm soát việc tạo cá thể. Theo như thiết lập biến thành viên, tôi đã luôn luôn nghe nói bạn không phải lo lắng về internals trong mocking/stubbing, chỉ giao diện công cộng. Vì vậy, chỉ cần trả lại giá trị chính xác cho phương thức phụ thuộc vào '@ x'. Tôi có thể sai mặc dù – bluehavana

16

tôi đã tìm thấy giải pháp này trên http://pivotallabs.com/introducing-rr/

new_method = A.method(:new) 

A.stub!(:new).and_return do |*args| 
    a = new_method.call(*args) 
    a.should_receive(:do_something).and_return(23) 
    a 
end 
2

tôi làm như Denis Barushev câu trả lời. Và tôi muốn đề nghị chỉ có một thay đổi mỹ phẩm mà làm cho new_method biến không cần thiết. Rspec không munge về phương pháp stubbed, để họ có thể được truy cập với proxied_by_rspec__ tiền tố:


A.stub!(:new).and_return do |*args| 
    a = A.proxied_by_rspec__new(*args) 
    a.should_receive(:do_something).and_return(23) 
    a 
end 
+0

Đây thực sự là một ý tưởng hay nhưng nó không hoạt động với phiên bản RSpec mà tôi đang sử dụng. Câu trả lời của Denis không hoạt động. – emk

+0

Cảm ơn! Có, nó rất phụ thuộc vào quy ước tiền tố tên "proxied_by_rspec__" có thể không phải là một phần của API được xuất bản. Oh, và ".call" không cần thiết trên dòng thứ hai, xin lỗi. BTW bạn đang sử dụng phiên bản RSpec nào? –

0

Dưới đây là một ý tưởng mà có thể không được rất tao nhã nhưng về cơ bản là chắc chắn để làm việc:

Tạo một lớp nhỏ mà kế thừa lớp bạn muốn kiểm tra, ghi đè lên các phương pháp khởi tạo và gọi supersau đã tạo ra khai trong khởi tạo, như vậy:

it "should call during_init in initialize" do 
    class TestClass < TheClassToTest 
    def initialize 
     should_receive(:during_init) 
     super 
    end 
    end 
    TestClass.new 
end 

và có yo u đi! Tôi chỉ sử dụng thành công trong một trong các bài kiểm tra của tôi.

0

Đá quý rspec_candy đi kèm với phương pháp trợ giúp stub_any_instance hoạt động trong cả RSpec 1 và RSpec 2.

2

Trong RSpec 2.6 hoặc mới hơn, bạn có thể sử dụng

A.any_instance.stub(do_something: 23) 

Xem the docs để biết thêm chi tiết. (Nhờ rogerdpack để chỉ ra rằng điều này hoàn toàn có thể - Tôi nghĩ nó xứng đáng một câu trả lời của riêng mình)

3

Trong phiên bản mới nhất của RSpec đến ngày hôm nay - 3.5 bạn có thể:

allow_any_instance_of(Widget).to receive(:name).and_return("Wibble") 
Các vấn đề liên quan