Schreiben Sie einfach einen kleinen Decorator, der sowohl das explizite als auch das implizite Starten des Servers behandelt und mit dem Sie feststellen können, ob der Server gestartet wurde.
Stellen Sie sich der reale Server sein, der gestartet werden muss:
class ServiceWrapper < BasicObject
def initialize(&start_procedure)
@start_procedure = start_procedure
end
def started?
[email protected]
end
def instance
@instance ||= @start_procedure.call
end
alias start instance
private
def method_missing(method_name, *arguments)
instance.public_send(method_name, *arguments)
end
def respond_to?(method_name)
super || instance.respond_to?(method_name)
end
end
Jetzt können Sie diese wie folgt in Ihren Angaben gelten:
class TheActualServer
def initialize
puts 'Server starting'
end
def operation1
1
end
def operation2
2
end
def kill
puts 'Server stopped'
end
end
Der wiederverwendbare Dekorateur könnte wie folgt aussehen :
Wenn eine Methode auf dem Decorator aufgerufen wird, wird es seine eigene IM ausführen Ergänzung, wenn eine existiert.Wenn zum Beispiel #started?
aufgerufen wird, wird es antworten, ob der tatsächliche Server gestartet wurde oder nicht. Wenn es keine eigene Implementierung dieser Methode hat, delegiert es den Methodenaufruf an das von ihm zurückgegebene Serverobjekt. Wenn es zu diesem Zeitpunkt keinen Verweis auf eine Instanz des tatsächlichen Servers hat, wird das bereitgestellte start_procedure
ausgeführt, um eins zu erhalten und dieses für zukünftige Aufrufe zu notieren.
Wenn Sie alle geschrieben Code in eine server_spec.rb
Datei mit dem Namen setzen können Sie dann führen Sie es mit:
rspec server_spec.rb
Die Ausgabe wird so sein:
something
Server starting
Server stopped
should eql 1
Server starting
Server stopped
should eql 2
should be a kind of Numeric
when server is running
Server starting
Server stopped
should be a kind of String
Server starting
Server stopped
should be a kind of Regexp
Finished in 0.00165 seconds (files took 0.07534 seconds to load)
5 examples, 0 failures
Beachten Sie, dass in den Beispielen 1 und 2 werden Methoden auf dem Server aufgerufen, und daher sehen Sie die Ausgabe des Servers, der implizit vom Decorator gestartet wird.
In Beispiel 3 gibt es überhaupt keine Interaktion mit dem Server, daher sehen Sie die Ausgabe des Servers nicht im Protokoll.
Dann gibt es wiederum in Beispiel 4 und 5 keine direkte Interaktion mit dem Serverobjekt im Beispielcode, aber der Server wird explizit durch einen Vorherblock gestartet, der auch in der Ausgabe zu sehen ist.
Ich könnte etwas ähnliches tun, aber anstatt das let (: server) {} im Block der obersten Ebene describe zu haben, verschiebe es in den Kontext "mit Server", entferne das before (: each) {} und dann das after (: each}} würde funktionieren ... – rynojvr
@MichaelPapile: block wird nur einmal im Kontext aufgerufen, also sollte der after-Block gut funktionieren –
@MichaelPapile: Ich hatte Probleme mit let() vor, und einige der let() s-Effekte zu existieren, aber noch nicht existierend, weil das let(), das es verursacht hat, noch nicht referenziert wurde.Ich benutzte einen Workaround, bevor ich von let!() wusste, in dem ich hatte einen before (: each) -Block, der einfach aus dem Namen des beleidigenden let() bestand, was bedeutet, dass der Kontext von let() sich auf den before (: each) -Block für diesen Test erstreckt und vernünftigerweise das after enthalten sollte (: jeder) Block auch. – rynojvr