Bibliothek für Stubbing und Festlegen der Erwartungen an HTTP -Anfragen in Ruby.
Stubbing HTTP -Anforderungen auf niedriger HTTP -Client -LIB -Ebene (müssen keine Tests ändern, wenn Sie die HTTP -Bibliothek ändern)
Setzen und Überprüfung der Erwartungen an HTTP -Anfragen
Übereinstimmende Anforderungen basierend auf Methode, URI, Header und Körper
Smart Matching der gleichen URIs in verschiedenen Darstellungen (auch codierte und nicht codierte Formen)
Smart Matching der gleichen Header in verschiedenen Darstellungen.
Unterstützung für Test :: Einheit
Unterstützung für RSPEC
Unterstützung für Minitest
Async :: Http :: Client
Bordstein (derzeit nur Curb :: Easy)
EM-http-Request
Excon
Httpclient
HTTP -Edelstein (auch bekannt als http.rb)
httpx
Manticore
Net :: http und andere Bibliotheken basierend auf net :: http, z. B.:
Httparty
Rest Client
Patron
Typhoeus (derzeit nur Typhoeus :: Hydra)
MRT 2.6
MRT 2.7
MRT 3.0
MRT 3.1
MRT 3.2
MRT 3.3
Jruby
Gem -Installieren Sie Webmock
oder alternativ:
# Zu Ihrer GemFileGroup hinzufügen: Test do do Edelstein "Webmock" Ende
Git Clone http://github.com/bblimke/webmock.gitcd webmock Recheninstallation
WebMock 2.x hat sich seit Version 1.x etwas verändert. Änderungen sind in ChangeLog.md aufgeführt
Erstellen Sie eine features/support/webmock.rb
mit dem folgenden Inhalt:
benötigen "Webmock/Gurke"
Fügen Sie den folgenden Code hinzu, um test/test_helper
:
benötigen "Webmock/Minitest"
Fügen Sie den folgenden Code zu spec/spec_helper
hinzu:
benötigen 'Webmock/rspec'
Fügen Sie den folgenden Code hinzu, um test/test_helper.rb
benötigen 'Webmock/test_unit' '
Sie können WebMock auch außerhalb eines Testframeworks verwenden:
benötigen 'webmock'include webmock :: apiwebmock.enable!
stub_request (: any, "www.example.com") net :: http.get ("www.example.com", "/") # ===> Erfolg
stub_request (: post, "www.example.com"). mit (Körper: "ABC", Header: {'Content-Length' => 3}) uri = uri.parse ("http://www.example.com/") req = net :: http :: post. new (uri.Path) req ['inhaltliche Länge'] = 3res = net :: http.start (uri.host, uri.port) do | http | http.request (req, "abc") end # ===> Erfolg
stub_request (: post, "www.example.com"). mit (Body:/World $/, Header: {"Content-Type" => /image/.+/}). to_return (Körper: "abc") uri = uri.parse ('http://www.example.com/') req = net :: http :: post.new (uri.path) req ['content-type' ' ] = 'Bild/png'res = net :: http.start (uri.host, uri.port) do | http | http.Request (REQ, 'Hello World') End # ===> Erfolg
stub_request (: post, "www.example.com"). mit (Körper: {Daten: {a: '1', b: 'fünf'}}) rastClient.post ('www.example.com', "Data [a] = 1 & data [b] = fünf", content_type: 'application/x-www-form-urlencoded') # ===> successRestclient.post ('www.example.com', '{"Daten": {"A": "1", "B": "fünf"}}', content_type: 'application /json') # ===> successRestClient.post ('www.example.com', '<data a = "1" b = "fünf" />',, content_type: 'application/xml') # ===> Erfolg
stub_request (: post, "www.example.com"). mit (Körper: Hash_including ({Daten: {a: '1', b: 'fünf'}}) restClient.post ('www.example.com', "Daten [a] = 1 & data [b] = fünf & x = 1 ",: content_type => 'Anwendung/x-www-form-urlencoded') # ===> Erfolg
stub_request (: any, "www.example.com"). With (Header: {'Header-Name' => 'Header-Value'}) uri = uri.parse ('http://www.example.com/') req = net :: http :: post.new ( Uri.Path) req ['Header-name'] = 'Header-Value'res = net :: http.start (Uri.host, Uri.port) do | http | http.request (req, 'abc') Ende # ===> Erfolg
stub_request (: Get, 'www.example.com'). With (Header: {'Accept' => ['Image/JPEG', 'Image/png']}) req = net :: http :: get.new ("/") req ['accept'] = [' Image/png '] req.add_field (' Akzeptieren ',' Image/jpeg ') net :: http.start ("www.example.com") {| http | http.request (req)} # ===> Erfolg
stub_request (: post, "www.example.com"). Mit {| Anfrage | request.body == "abc"} rastclient.post ('www.example.com', 'ABC') # ===> Erfolg
stub_request (: get, "www.example.com"). mit (Basic_auth: ['Benutzer', 'Pass'])# oder# stub_request (: Get, "www.example.com").# mit (Header: Oder req = net :: http :: get.new ('/') req.basic_auth 'user', 'pass' http.request (req) end # ===> Erfolg
stub_request(:get, "user:[email protected]")
stimmt nicht mit einer Anfrage mit Anmeldeinformationen überein, die im Autorisierungsheader bereitgestellt werden.stub_request (: Get, "Benutzer: [email protected]") rastclient.get ('Benutzer: [email protected]') # ===> Erfolg
stub_request (: any, /example/)net::http.get('www.example.com ','/') # ===> Erfolg
stub_request (: any, -> (uri) {true})
Uri_template = adressable :: template.new "www.example.com/ <Sid}/"stub_request(:any, Uri_template) net :: http.get ('www.example.com', '/webmock/') # = ==> Erfolg
Uri_template = Adressable :: template.new "www.example.com/thing/iN.json <:?x,yZ} <sother* "Stub_request(:Any, Uri_template) net :: http.get ('www. Beispiel.com ', '/Thing/5.json?x=1&y=2&z=3&anyparam=4') # ===> Erfolg
stub_request (: Get, "www.example.com"). Mit (Abfrage: {"A" => ["B", "C"]}) rastClient.get ("http://www.example.com/ a [] = B & a [] = C ") # ===> Erfolg
stub_request (: Get, "www.example.com"). mit (Abfrage: Hash_including ({"a" => ["B", "c"]}) restclient.get ("http://www.example.com/?a=B&a..a=C&x= 1 ") # ===> Erfolg
stub_request (: Get, "www.example.com"). mit (Abfrage: Hash_Excluding ({"a" => "B"}) rastclient.get ("http://www.example.com/?a=B") # ===> failerestclient.get ("http : //www.example.com/? a = c ") # ===> Erfolg
stub_request (: any, "www.example.com"). to_return (Körper: "ABC", Status: 200, Header: {'Inhaltslänge' => 3}) net :: http.get ("www.example.com", '/') # ===> " ABC"
Legen Sie den entsprechenden Inhaltstyp für parsed_response
von Httparty fest.
stub_request (: any, "www.example.com"). to_return body: '{}', Header: {content_type: 'application/json'}
Datei.open ('/tmp/response_body.txt', 'w') {| f | F.puts 'ABC'} stub_request (: any, "www.example.com"). to_return (Körper: Datei.New ('/tmp/response_body.txt'), Status: 200) net :: http.get ('www.example.com', '/') # ===> "ABCN"
stub_request (: any, "www.example.com"). to_return_json (Körper: {foo: "bar"}) net :: http.get ('www.example.com', '/') # ===> "{" foo ":" bar "}"
stub_request (: any, "www.example.com"). to_return (Status: [500, "interner Serverfehler"]) req = net :: http :: get.new ("/") net :: http.start ("www.example.com") {| http | http.request (req)}. Meldung # ===> "Interner Serverfehler"
curl -is
aufgezeichnet wurden curl -is www.example.com > /tmp/example_curl_-is_output.txt
raw_response_file = file.new ("/tmp/example_curl_-is_output.txt"))
aus der Datei
stub_request (: Get, "www.example.com"). to_return (raw_response_file)
oder Zeichenfolge
stub_request (: Get, "www.example.com"). to_return (raw_response_file.read)
stub_request (: any, 'www.example.net'). to_return {| Anfrage | {Body: Request.body}} rastClient.post ('www.example.net', 'ABC') # ===> "ABCN"
stub_request (: any, 'www.example.net'). to_return (lambda {| request | {body: request.body}}) rastClient.post ('www.example.net', 'abc') # ===> "ABCN"
curl -is
aufgezeichnet wurden curl -is www.example.com > /tmp/www.example.com.txt
stub_request (: Get, "www.example.com"). to_return (lambda {| request | file.new ("/tmp/#{request.uri.host.to_s} .txt")})
stub_request (: any, 'www.example.net'). to_return (Körper: lambda {| request | request.body}) restclient.post ('www.example.net', 'abc') # ===> "ABCN"
Klasse myrackapp Def self.call (env) [200, {}, ["Hallo"]] endendStub_request (: Get, "www.example.com"). TO_RACK (myrackapp) rastClient.post ('www.example.com') # ===> "Hallo"
stub_request (: any, 'www.example.net'). to_raise (StandardError) rastClient.post ('www.example.net', 'ABC') # ===> StandardError
stub_request (: any, 'www.example.net'). to_raise (StandardError.New ("ein Fehler"))
stub_request (: any, 'www.example.net'). to_raise ("ein Fehler")
stub_request (: any, 'www.example.net'). to_timeoutrestclient.post ('www.example.net', 'ABC') # ===> rastClient :: RequestTimeout
stub_request (: Get, "www.example.com"). to_return ({body: "abc"}, {body: "def"}) net :: http.get ('www.example.com', '/') # ===> "abcn" net :: http. Get ('www.example.com', '/') # ===> "Defn" #After Alle Antworten werden verwendet. Die letzte Antwort wird infinitailNide :: http.get ('www.example.com', ',', zurückgegeben. ' /') # ===> "Defn"
to_return()
, to_raise()
oder to_timeout
deklarationenstub_request (: Get, "www.example.com"). to_return ({body: "abc"}). Dann. #Then () ist nur ein syntaktischer Zucker to_return ({body: "def"}). Dann. to_raise (myException) net :: http.get ('www.example.com', '/') # ===> "abcn" net :: http.get ('www.example.com', '/') # ===> "Defn" net :: http.get ('www.example.com', '/') # ===> myException erhöht
stub_request (: Get, "www.example.com"). to_return ({body: "abc"}). mal (2) .then. to_return ({body: "def"}) net :: http.get ('www.example.com', '/') # ===> "abcn" net :: http.get ('www.example.com ','/') # ===> "abcn" net :: http.get (' www.example.com ','/') # ===> "Defn"
stub_get = stub_request (: get, "www.example.com") remove_request_stub (stub_get)
Webmock.allow_net_connect! "ABC" net :: http.get ('www.saething.com', '/') # ===> /.+Something.+/Webmock.Disable_net_connect!net::Http.get(''www.Soming. com ','/') # ===> Fehler
Webmock.disable_net_connect! (DegoLocalhost: true) net :: http.get ('www.saething.com', '/') # ===> failureNet :: http.get ('localhost: 9887', '/') # ====> erlaubt. Vielleicht zu Selen?
Zulässige Anforderungen können auf verschiedene Weise angegeben werden.
Mit einer String
, in der ein Hostnamen angegeben wird:
Webmock.disable_net_connect! (Erlauben: 'www.example.org') rastclient.get ('www.saething.com', '/') # ==> failurerestclient.get ('www.example.org', '//////////////// ') # ===> erlaubteRestclient.get (' www.example.org:8080 ','/') # ===> erlaubt
Mit einer String
, die einen Hostnamen und einen Port angibt:
Webmock.disable_net_connect! (Erlauben: 'www.example.org '/') # ===> failurerestclient.get ('www.example.org:8080', '/') # ===> erlaubt
Mit einem Regexp
der dem URI entspricht:
Webmock.disable_net_connect! (Erlauben: %r {amne.org/foo}) rastClient.get ('www.example.org', '/foo/bar') # ===> erlaubteRestclient.get ('sample.org' , '/foo') # ===> erlaubteRestclient.get ('sample.org', '/bar') # ===> Fehler
Mit einem Objekt, das auf #call
reagiert, ein URI
-Objekt erhält und einen Booleschen Rückgaberegel zurückgibt:
Denylist = ['google.com', 'facebook.com', 'Apple.com'] erlaubt_sites = lambda {| uri | Denylist.none? {| Site | Uri.host.include? (Site)}} webmock.disable_net_connect! (erlaubt: erlaubte_sites) rastClient.get ('www.example.org', '/') # ===> erlaubteRestclient.get ('www.factocebook. com ','/') # ===> failurerestclient.get (' Apple.com ','/') # ===> Fehler
Mit einer Array
von einem der oben genannten:
Webmock.disable_net_connect! (Erlauben: [ lambda {| uri | Uri.host.length % 2 == 0}, /ample.org/,, 'bbc.co.uk',]) restclient.get ('www.example.org', '/') # ===> erlaubteRestclient.get ('bbc.co.uk', '/') # == => Erlaubt
Das HTTP -Protokoll hat 3 Schritte: Verbinden, Anforderungen und Antwort (oder 4 mit Schluss). Die meisten Ruby HTTP -Client -Bibliotheken behandeln Connect als Teil des Anforderungsschritts mit Ausnahme von Net::HTTP
, mit dem die Verbindung zum Server separat zur Anforderung geöffnet wird, indem Net::HTTP.start
verwendet wird.
Die Webmock -API wurde auch mit Connect entworfen, das Teil des Anforderungsschritts war, und ermöglicht nur Stubbing -Anforderungen, nicht Verbindungen. Wenn Net::HTTP.start
aufgerufen wird, weiß Webmock noch nicht, ob eine Anfrage gestoppt ist oder nicht. WebMock verzögert standardmäßig eine Verbindung, bis die Anforderung aufgerufen wird. Wenn also keine Anfrage vorhanden ist, tut Net::HTTP.start
nichts. Dies bedeutet, dass WebMock standardmäßig das Net :: HTTP -Verhalten bricht!
Um dieses Problem zu verarbeiten, bietet WebMock -Angebote :net_http_connect_on_start
Option, die an WebMock.allow_net_connect!
und WebMock.disable_net_connect!
Methoden, dh
Webmock.allow_net_connect! (Net_http_connect_on_start: true)
Dies zwingt WebMock Net :: HTTP -Adapter, immer mit Net::HTTP.start
eine Verbindung herzustellen. Zum Zeitpunkt der Verbindung gibt es noch keine Informationen über die Anfrage oder die URL. Daher kann WebMock nicht entscheiden, ob eine Anfrage gestoppt werden soll oder nicht und alle Verbindungen zulässig sind. Um Verbindungen nur zu einer bestimmten Domäne (z. B. Ihrem Testserver) zu aktivieren: Verwendung:
Webmock.allow_net_connect! (Net_http_connect_on_start: "www.example.com")
benötigen 'webmock/test_unit'stub_request (: any, "www.example.com") uri = uri.parse (' http://www.example.com/ ') req = net :: http :: post.new (New ( URI.Path) req ['Inhaltslänge'] = 3res = net :: http.start (uri.host, uri.port) do | http | http.request (req, 'abc') endassert_requested: post, "http://www.example.com", Header: {'Inhaltslänge' => 3}, Körper: "ABC", Zeiten: 1 # ===> successassert_not_requested: Get "http://www.saething.com" # ===> successassert_requested (: post, "http://www.example.com", ",", ",", Zeiten: 1) {| req | req.body == "abc"}
Webmock.allow_net_connect! Net :: http.get ('www.example.com', '/') # ===> successassert_requested: Get, "http://www.example.com" # ===> Erfolg
stub_get = stub_request (: get, "www.example.com") stub_post = stub_request (: post, "www.example.com") net :: http.get ('www.example.com', '/') Assert_Requested (stub_get) assert_not_requested (stub_post)
WebMock
-ModulDieser Stil wird von FakeWeb-Matcher ausgeliehen
benötigen 'webmock/rspec'exect (webmock) .to Have_Requested (: Get "www.example.com"). Mit (Körper: "ABC", Header: {'Content-Length' => 3}). TOALEPECT (WebMock) .not_to Have_Requested (: Get "," www.Something.com ") erwarten (Webmock). To Have_Requested (:: Beitrag, "www.example.com"). mit {| req | req.body == "ABC"}# Beachten Sie, dass der Block mit "do ... end" anstelle von lockigen Klammern nicht funktioniert!# Warum? Siehe diesen Kommentar https://github.com/bblimke/webmock/issues/174#issuecoment-34908908Expect(Webmock).to Have_Requested (: Get "www.example.com"). mit (Abfrage: {"a" => ["b", "c"]}) erwarten (webmock) .to Have_Requested (: Get, "www.example.com"). mit (Abfrage: Hash_including ({"A" => ["B", "C"]}) erwarten (webmock) .to Have_Requested (: Get, "www.example.com"). mit (Körper: {"a" => ["b", "c"]}, Header: {'content-type' => 'application/json'})
a_request
erwarten (a_request (: post, "www.example.com"). mit (Körper: "ABC", Header: {'Inhaltslänge' => 3})). zu haben_been_made.onceExect (a_request (: post, "www.something.com")). zu haben_been_made.times (3) erwarten (a_request (: post "," www.something.com "). zu haben_been_made.at_least_oncexepepect (a_request (a_request (a_requestexepe (: Post, "www.saething.com")). zu haben_been_made.at_least_times (3) erwarten (a_request (: post, "www.saething.com"). An Have_been_Made.at_ Most_twiceExpect (a_request (: post "," www.Sometht.com "). Zu Have_been_Made.at_mod_most_times (3times (3times (3times (3times) (3Times). ) erwarten (a_request (: anwes . zu haben_been_madeexpect (a_request (: Get, "www.example.com"). Mit (Abfrage: {"a" => ["B", "c"]}). zu haben_been_madeexpect (a_request (: Get "www.example.com"). mit (Abfrage: Hash_including ({"a" => ["b", "c"]})). mit (Körper: {"a" => ["b", "c"]}, Header: {'content-type' => 'application/json'}).
stub = stub_request (: get, "www.example.com")# ... Anfragen machen ... erwarten (stub) .to Have_been_Requested
Wenn Sie alle aktuellen Stubs und den Verlauf der Anfragen zurücksetzen möchten, verwenden Sie WebMock.reset!
stub_request (: any, "www.example.com") net :: http.get ('www.example.com', '/') # ===> successwebmock.reset! net :: http.get ('www .example.com ','/') # ===> failureassert_not_requested: Get, "www.example.com" # ===> Erfolg
Wenn Sie nur die Zähler der ausgeführten Anforderungen zurücksetzen möchten, verwenden Sie WebMock.reset_executed_requests!
stub = stub_request (: get, "www.example.com") stub2 = stub_request (: get, "www.example2.com") net :: http.get ('www.example.com', '/') net :: http.get ('www.example.com', '/' )net::http.get(''www.example2.com ',' /')expect(stub). .
# Webmock (alle Adapter) webmock.Disable!# Webmock für alle LIBs außer Net :: httpwebmock.Disable! (Ausgenommen: [: net_http])# Aktivieren Sie Webmock (alle Adapter) webmock.enable!# Enable webmock für alle libmock für alle libs aktivieren außer Patronwebmock.Enable! (Außer: [: Patron])
Eine ausgeführte Anfrage entspricht einer stubigen Anfrage, wenn sie nach den Kriterien übergeht:
Wenn URI -Anforderung übereinstimmt, haben Sie die URI -Zeichenfolge, das Regexp -Muster oder die RFC 6570 URI -Vorlage
Und Anforderungsmethode entspricht der Stubbed -Anforderungsmethode oder einer Stubbed -Anforderungsmethode: Any: beliebt
Und die Anforderungsbehörde entspricht dem Stubbed -Anforderungsbehörde oder der Stubbed -Anforderungsbehörde ist nicht angegeben
Und Anforderungsheader übereinstimmen Stubbed -Anforderungs -Header oder Stubbed -Anforderungsheader übereinstimmen mit einer Teilmenge von Anforderungsheadern, oder Stubbed -Anforderungsheader sind nicht angegeben
Und Anforderungsübereinstimmungen, die Block oder Block angegeben haben, werden nicht bereitgestellt
Immer der zuletzt deklarierte Stub, der mit der Anfrage übereinstimmt, wird angewendet, dh:
stub_request (: get, "www.example.com"). to_return (Körper: "ABC") stub_request (: get, "www.example.com"). TO_RETURN (Körper: "def") net :: http.get ('www.example.com', '/') # ====> "def"
WebMock passt zu allen Darstellungen desselben URI.
Dh alle folgenden Darstellungen der URI sind gleich:
"www.example.com" "www.example.com/" "www.example.com:80" "www.example.com:80/" http://www.example.com "http: // www.example.com/"s"http://www.example.com:80""http://www.example.com:80/ "
Die folgenden URIs mit userInfo sind auch für WebMock gleich
"A B: [email protected]" "a b: [email protected]/" "a b: [email protected]: 80" "a b: [email protected]: 80/" "http: // a b: [email protected]" "http: // a b: [email protected]/" "http: // a b: [email protected]: 80" "http : // a b: [email protected]: 80/"" a%20b: [email protected] "" a%20b: [email protected]/"" a%20b: Pass@ www.example.com:80""a%20b:[email protected]:80/""http://a%20b:[email protected] "HTTP://a%20B: [email protected]/ "" http: //%20b: [email protected]: 80 "" http: // a%20b: [email protected]: 80/"
oder diese
"www.example.com/my path/? a = mein param & b = c" "www.example.com/my%20path/?a=My%20param&b=c" www.example.com:80/my path/ ? C "" http://www.example.com/my%20path/?a=My%20Param&b=c "" http://www.example.com:80/my path/? A = My Param & B = C " "http://www.example.com:80/my%20path/?a=my%20param&b=c"
Wenn Sie REGEXP für die Entfernung von URI angeben, wird WebMock versuchen, sie mit jeder gültigen Form derselben URL zu entsprechen.
Dh /my path/
wird mit www.example.com/my%20path
übereinstimmen, da er entsprechend www.example.com/my path
entspricht
Wenn Sie adressable :: Vorlage für die Übereinstimmung verwenden, verschoben WebMock die Übereinstimmungsregeln auf adresable, was RFC 6570 entspricht.
Wenn Sie eine der Webmock -Methoden für die Abfrageparameter verwenden, wird adresable verwendet, um die Basis -URI zu entsprechen, und WebMock stimmt mit den Abfragungsparams überein. Wenn Sie dies nicht tun, lässt WebMock die adressierbare URI übereinstimmen.
WebMock wird in den folgenden Situationen Anforderungsüberschriften gegen Stubbed Request Header übereinstimmen:
Die Stubbed -Anfrage enthält angegebene Header und Anforderungsheader sind die gleichen wie Stubbed Header
IE Stubbed Header: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
, angefordert: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
Stubbed Request hat angegeben, und Stubbed Request Header sind eine Untergruppe von Anforderungsheadern
IE Stubbed Header: { 'Header1' => 'Value1' }
, angefordert: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
Stubne Anfrage hat keine Header
IE Stubbed Header: nil
, angefordert: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
Webmock normalisiert Header und behandelt alle Formen derselben Header als gleich: IE Die folgenden zwei Sätze von Header sind gleich:
{ "Header1" => "value1", content_length: 123, X_CuStOm_hEAder: :value }
{ header1: "value1", "Content-Length" => 123, "x-cuSTOM-HeAder" => "value" }
Um die realen HTTP -Interaktionen Ihrer Anwendung aufzuzeichnen und später in Tests wiederzugeben, können Sie VCR mit Webmock verwenden.
Webmock.after_request do | request_signature, Antwort | Puts "Anfrage #{Request_signature} wurde gemacht und #{Antwort} wurde zurückgegeben" Ende
Webmock.after_request (außer: [: Patron], real_requests_only: true) do | req_signature, Antwort | setzt "Anfrage #{req_signature} wurde gemacht und #{response} wurde zurückgegeben."
Bitte senden Sie sie hier http://github.com/bblimke/webmock/issues
Sie können einen Beitrag durch Tribating -Probleme leisten, die die Reproduzierung von Fehlerberichten oder die Frage nach wichtigen Informationen wie Versionsnummern oder Reproduktionsanweisungen enthalten können. Wenn Sie Probleme mit Triangieren beginnen möchten, besteht eine einfache Möglichkeit, den Einstieg für Webmock für die Codetia zu abonnieren.
Wenn Sie Vorschläge zur Verbesserung von Webmock haben
Ich bin besonders daran interessiert, wie die DSL verbessert werden könnte.
Um an Webmock zu arbeiten, müssen Sie zunächst das Repo aufgeben und klonen. Bitte arbeiten Sie an einer engagierten Filiale und rebase gegen Master, bevor Sie eine Pull -Anfrage senden.
Die ursprünglichen Zeilen dieses Projekts wurden am neuen Bambus -Hack -Tag geschrieben, dank meiner Bambinos Kollegen für all die großartigen Vorschläge!
Personen, die Patches und neue Funktionen eingereicht oder Verbesserungen vorgeschlagen haben. Vielen Dank an diese Leute:
Ben Pickles
Mark Evans
Ivan Vega
Piotr usewicz
Nick Plantte
Nick Quaranto
Diego E. "Flameeyes" Petttenò
Niels Meerschaert
Mack Earnhardt
Arvicco
Sergio Gil
Jeffrey Jones
Tekin Sulyman
Tom Ward
Nadim Bitar
Myron Marston
Sam Phillips
Jose Angel Cortinas
Riezise
Steve Tooke
Nathaniel Bibler
Martyn Loughran
Muness Alrubaie
Charles Li
Ryan Bigg
Pete Higgins
Hans de Graaff
Alastair Brunton
Sam Stokes
Eugene Bolshakov
James Conroy-Finn
Salvador Fuentes jr
Alex Rothenberg
Aidan Feldman
Steve Hull
Jay Adkisson
Zach Dennis
Nikita Fedyashev
Lin Jen-shin
David Yeu
Andreas Garnæs
Roman Shterenzon
Chris McGrath
Stephen Celis
Eugene Pimenov
Albert Llop
Christopher Pickslay
Tammer Saleh
Nicolas Fouché
Joe van Dyk
Mark Abramov
Frank Schumacher
Dimitrij Denissenko
Marnen Laibow-Koser
Evgeniy Dolzhenko
Nick Recobra
Jordan Elver
Joe Karayusuf
Paul Cortens
Jugyo
Aindustries
Eric Oestrich
Erwanlr
Ben Bleything
Jon Leighton
Ryan Schlesinger
Julien Boyer
Kevin Glowacz
Hans Hasselberg
Andrew Frankreich
Jonathan Hyman
Rex Feng
Pavel Forkert
Jordi Massaguer Pla
Jake Benilov
Tom Beauvais
Mokevnin Kirill
Alex Grant
Lucas Dohmen
Bastien Vaucher
Joost Baaij
Joel Chippindale
Murahashi Sanemat Kenichi
Tim Kurvers
Ilya Vassilevsky
Gotwalt
Leif Blatt
Alex Tomlins
Mitsutaka Mimura
Tomy Kaira
Daniel Van Hoesel
Ian Asaff
Ian Lesperance
Matthew Horan
Dmitry Gutov
Florian Dütsch
Manuel Meurer
Brian D. Burns
Riley stark
Tamir Duberstein
Stefano Uliari
Alex Stupakov
Karen Wang
Matt Burke
Jon Rowe
Aleksey V. Zapparov
PRAVEEN ARIMBRATHODIYIL
Bo Jeanes
Matthew Conway
Rob Olson
Max Lincoln
Oleg Gritsenko
Hwan-joon Choi
Shibata Hiroshi
Caleb Thompson
Theo Hultberg
Pablo Jairala
Insoo Buzz Jung
Carlos Alonso Pérez
Trlorenz
Alexander Simonov
Thorbjørn Hermanse
Mark Lorenz
tjsousa
Tasos Stathopoulos
Dan Buettner
Sven Riedel
Mark Lorenz
Dávid Kovács
Fishermand46
Franky Wahl
Chayoung du
Simon Russell
Steve Mitchell
Mattias Putman
Zachary Anker
Emmanuel Sambo
Ramon Tayag
Johannes Schlumberger
Siôn Le Roux
Matt Palmer
Zhao Wen
Krzysztof Rygielski
Magne Land
Yurivm
Mike Knepper
Charles Pence
Alexey Zapparov
Pablo Brasero
Cedric Pimenta
Michiel Karnebeek
Alex Kestner
Manfred Stienstra
Tim Diggins
Gabriel Chaney
Chris Griego
Taiki Ono
Jonathan Schatz
Jose Luis Honorato
Aaron Kromer
Pavel Jurašek
Jake wert
Gabe Martin-Dempesy
Michael Grosser
Aleksei Maridashvili
Ville Lautanala
Koichi Ito
Jordan Harband
Tarmo Tänav
Joe Marty
Chris Thomson
Vít Ondräng
George Ulmer
Christof Koenig
Chung-yi Chi
Olexandr Hoshylyk
Janko Marohnić
Pat Allan
Rick -Lied
Naruse, Yui
Piotr Boniecki
Olia Kremmyda
Michał Matyas
Matt Brictson
Kenny Ortmann
Redbar0n
Lukas Pokorny
Arkadiy Tetelman
Kazato Sugimoto
Olle Jonsson
Pavel Rosický
Geremia Taglialatela
Koichi Sasada
Yusuke Endoh
Grauer Bäcker
Soonkhen Owyong
Pavel Valena
Adam Sokolnicki
Jeff Felchner
Eike senden
Claudio Poli
Csaba apagyi
Frederick Cheung
Fábio D. Batista
Andriy Yanko
y-yagi
Rafael França
George Claghorn
Alex Junger
Orien Madgwick
Andrei Sidorov
Marco Costa
Ryan Davis
Brandur
Samuel Williams
Patrik Ragnarsson
Alex Coomans
Vesa Laakso
John Hawthorn
Guppy0356
Thilo Rusche
Andrew Stuntz
Lucas Uyezu
Bruno Sutic
Ryan Kerr
Adam Harwood
Ben Koshy
Jesse Bowes
Marek Kasztelnik
CE07C3
Jun Jiang
Oleksiy Kovyrin
Matt Larraz
Tony Schneider
Niklas Hösl
Johanna Hartmann
Alex Vondrak
Will Storey
Eduardo Hernandez
Ojab
Giorgio Gambino
Timmitry
Michael Fairley
Ray Zane
Geh Sueyoshi
Cedric Sohrruer
Akira Matsuda
Mark Spangler
Henrik Nyh
Yoann Lecuyer
Lucas Arnaud
Marc Rohloff
Inkstak
Yuki Inoue
Brandon Weaver
Josh Nichols
Ricardo Trindade
Earlopain
James Brown
Kazuhiro Nishiyama
Étienne Barrié
Matt Brown
Victor Maslov
Gio Lodi
Ryan Brooks
Jacob Frautschi
Christian Schmidt
Rodrigo Argumedo
Für eine vollständige Liste der Mitwirkenden können Sie die Seite der Mitwirkenden besuchen.
Danke FakeWeb! Diese Bibliothek wurde von FakeWeb inspiriert. Ich habe einige Lösungen aus diesem Projekt in WebMock importiert. Ich habe auch einen Code kopiert, dh NET: HTTP -Adapter. FakeWeb Architecture erlaubte mir leider nicht, sie mit den von mir benötigten Funktionen leicht zu erweitern. Ich habe es auch vorgezogen, einige Dinge anders zu arbeiten, dh anfordern Stub -Vorrang.
Copyright (C) 2009-2010 Bartosz Blimke. Weitere Informationen finden Sie in Lizenz.