2009-07-22 15 views
32

Gibt es eine Möglichkeit, Kernel.sleep in einem RSPEC-Szenario zu stopfen?RSpec: Stubbing Kernel :: Schlaf?

+0

Suchen Sie etwas über Kernel :: stubs (: schlafen) –

+0

Ich könnte mir vorstellen, er würde wollen, dass es funktioniert und nicht schlafen, vielleicht verlangsamt seinen Test ... – Rich

Antwort

43

Wenn Sie anrufen Schlaf innerhalb der Kontext eines Objekts, sollten Sie es auf das Objekt, wie so Stummel:

class Foo 
    def self.some_method 
    sleep 5 
    end 
end 

it "should call sleep" do 
    Foo.stub!(:sleep) 
    Foo.should_receive(:sleep).with(5) 
    Foo.some_method 
end 

der Schlüssel ist, schlafen auf Stub was auch immer "Selbst" ist in dem Kontext, in dem der Schlaf genannt wird.

+1

Arbeitete gut für mich, Prost! – opsb

+0

Das Prüfobjekt zu stubben ist keine gute Idee. Beispiele: http://robots.thoughtbot.com/don-t-stub-the-system-under-test – georgebrock

+1

@georgebrock aus nicht relevanten Gründen, nicht wahr? Ich glaube [dies] (http://stackoverflow.com/a/27749263/52499) ist der Weg, der die Absicht am besten vermittelt. Und muss eine neuere Syntax verwenden. 'allow_any_instance_of (Object) .to receive (: sleep)' –

2

Wenn Sie Mocha verwenden, dann wird so etwas wie dies funktionieren:

def setup 
    Kernel.stubs(:sleep) 
end 

def test_my_sleepy_method 
    my_object.take_cat_nap! 
    Kernel.assert_received(:sleep).with(1800) #should take a half-hour paower-nap 
end 

Oder wenn Sie rr verwenden:

def setup 
    stub(Kernel).sleep 
end 

def test_my_sleepy_method 
    my_object.take_cat_nap! 
    assert_received(Kernel) { |k| k.sleep(1800) } 
end 

Sie wahrscheinlich sollte nicht mehr testen komplexe Threading-Probleme mit Komponententests. Verwenden Sie bei Integrationstests jedoch das echte Kernel.sleep, mit dem Sie komplexe Threading-Probleme ausfindig machen können.

4

In reiner rspec:

before do 
    Kernel.stub!(:sleep) 
end 

it "should sleep" do 
    Kernel.should_receive(:sleep).with(100) 
    Object.method_to_test #We need to call our method to see that it is called 
end 
+8

Um zu klären, weil dies nicht sofort für mich funktioniert, müssen Sie Kernel aufrufen .schlaf, um es auf diese Weise zu verspotten. Nur sofortiges Aufrufen des Schlafs schlägt fehl –

+0

Ja, die Methode, die Sie anrufen, wird den Schlaf darin haben. – nitecoder

0

Ich musste Stummel erfordern und nach langer Suche fand ich, dass der einzige Weg, die für mich gearbeitet ist dies

def method_using_sleep 
    sleep 
    sleep 0.01 
end 

it "should use sleep" do 
    @expectations = mock('expectations') 
    @expectations.should_receive(:sleep).ordered.with() 
    @expectations.should_receive(:sleep).ordered.with(0.01) 

    def sleep(*args) 
    @expectations.sleep(*args) 
    end 

    method_using_sleep 
end 
0

Ich konnte die anderen Lösungen hier nicht zum Funktionieren bringen. Vielleicht hat sich etwas in der Art und Weise geändert, wie der Schlaf in neueren Versionen von Ruby oder etwas anderem gehandhabt wird.

Was ich getan habe, war Affe-Patch Objekt Klasse, wie es scheint, dass dies ist, was die Schlafanrufe empfängt. Also fügte ich einfach folgendes hinzu:

class Object 
    def sleep(*args) 
    end 
end 

Also macht die Schlafmethode jetzt nichts statt etwas. Es könnte eine Möglichkeit geben, das besser zu verspotten, aber ich war nicht in der Lage, eine gute Lösung zu finden, ohne die sleep metohd jedes einzelnen Objekts zu verspotten, das sie möglicherweise benutzt hat.

+0

Siehe meine Lösung unten. Rspec-Mock ist hier, also müssen Sie nicht affektieren – Benj

11

Wenn der Anruf zu sleep nicht innerhalb eines Objekts ist (während eine Harke Aufgabe zum Beispiel Testen), können Sie die folgenden in einem vor-Block (rspec 3 Syntax) in

allow_any_instance_of(Object).to receive(:sleep)