2008-11-25 13 views

Antwort

22

Here's the commit which adds the feature to rspec - das war am 25. Mai 2008. Damit Sie

A.any_instance.stub(do_something: 23) 

jedoch tun können, das neueste Juwel v Die Version von rspec (1.1.11, Oktober 2008) enthält diesen Patch nicht.

This ticket besagt, dass sie es aus Wartungsgründen herausgerissen haben, und eine alternative Lösung wurde noch nicht zur Verfügung gestellt.

Sieht nicht so aus, als könnten Sie es zu diesem Zeitpunkt tun. Sie müssen die Klasse manuell hacken mit alias_method oder somesuch.

+3

dass es scheint, wurde mit 2.6.0 zurückgebracht, also ist es jetzt drin ... – rogerdpack

+3

@rogerdpack: In der Tat, endlich! http://blog.davidchelimsky.net/2011/05/12/rspec-260-is-released/ "Unterstützung für any_instance.stub und any_instance.should_receive hinzufügen" – tokland

+0

Irgendeine Idee, wenn Sie etwas direkt an diese Instanz anhängen möchten aber neu? wie sollte_receive (: blah) .exactlY (5) .x --- und du willst das nicht für irgendein Objekt, nur dieses spezifisch? – xaxxon

11

Ich weiß nicht, wie das Mock-Rahmen in spec ist zu tun, aber man kann es leicht für Mokka auslagern folgendes zu tun:

# 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

oder mit RR:

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

In meiner Version von rspec (1.2.2) Ich kann dies tun:

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

Ich weiß, dass es wahrscheinlich zu spät ist, um auf das ursprüngliche Plakat zu beantworten, aber ich antworte es trotzdem für die Zukunft, wie Ich bin mit der gleichen Frage hierher gekommen, habe aber herausgefunden, dass es an der neuesten rspec-Version gearbeitet hat.

+0

Das Verhalten Ihres Vorschlags ist nicht korrekt. Es ist die: do_something-Methode, die 42, nicht den Initialisierer zurückgibt. –

0

eine Instanz Methode, um Stummel, Sie so etwas tun kann:

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 

Aber wie pschneider wies darauf hin, kehren nur 42 auf neu mit: A.stub(:new).and_return(42) oder etwas in diesem Sinne.

+0

Ich denke, es geht darum, die Instanzmethode zu stubben, wenn Sie nicht die Kontrolle über die Erstellung der Instanzen in Ihrem Test haben. Außerdem gibt der Initialisierer 42 nicht zurück, sondern setzt eine Instanzvariable: Es ist die do_something-Methode, die 42 zurückgibt, die stubbed sein muss. –

+1

Die 'A.stub (: new) .and_return (@my_stub)' 'wird den Instanz-Stub jedes Mal zurückgeben, so dass Sie die Instanz erstellen können. Soweit ich die Member-Variable gesetzt habe, habe ich immer gehört, dass Sie sich nicht über Internal in Mocking/Stubbing sorgen, nur öffentliche Schnittstellen. Geben Sie einfach die korrekten Werte für die Methode zurück, die von '@ x' abhängt. Ich bin wahrscheinlich falsch, obwohl – bluehavana

16

ich diese Lösung habe auf 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

fand ich wie Denis Barushev Antwort tun. Und ich würde nur eine kosmetische Veränderung vorschlagen, die new_method Variable unnötig macht. Rspec tut munge auf Stub-Methoden, so dass sie mit proxied_by_rspec__ Präfix zugegriffen werden können:


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

Dies ist eine wirklich nette Idee, aber es funktioniert nicht mit der Version von RSpec ich benutze. Die Antwort von Denis funktioniert. – emk

+0

Danke! Ja, es ist sehr abhängig von der Präfixkonvention "proxied_by_rspec__", die nicht Teil der veröffentlichten API sein darf. Oh, und ".call" wird in der zweiten Zeile nicht benötigt, sorry. BTW welche RSpec Version verwendest du? –

0

Hier ist eine Idee, die nicht sehr elegant sein könnte, ist aber im Grunde sicher zu arbeiten:

eine kleine Klasse, die erbt die Klasse, die Sie testen wollen, die Methode initialize außer Kraft setzen und rufen supernach in der initialize die Stubs geschaffen zu haben, etwa so:

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

und es yo du gehst! Ich habe das gerade erfolgreich in einem meiner Tests verwendet.

0

Der rspec_candy Edelstein kommt mit einer stub_any_instance Hilfsmethode, die sowohl in RSpec 1 als auch in RSpec 2 funktioniert.

2

In RSpec 2.6 oder höher können Sie verwenden

A.any_instance.stub(do_something: 23) 

the docs Siehe für weitere Details. (Danke an rogerdpack für den Hinweis auf, dass dies jetzt möglich ist - ich dachte, es eine Antwort von selbst verdient)

3

In der neuesten Version von RSpec ab heute - 3.5 können Sie:

allow_any_instance_of(Widget).to receive(:name).and_return("Wibble") 
Verwandte Themen