Bibliothèque pour les attentes et la définition des attentes sur les demandes HTTP dans Ruby.
Les demandes HTTP SUNTP au niveau du client HTTP Client HTTP (pas besoin de modifier les tests lorsque vous modifiez la bibliothèque HTTP)
Définition et vérification des attentes sur les demandes HTTP
Demandes de correspondance basées sur la méthode, l'URI, les en-têtes et le corps
Correspondance intelligente des mêmes URI dans différentes représentations (également des formes codées et non codées)
Correspondance intelligente des mêmes en-têtes dans différentes représentations.
Prise en charge du test :: Unité
Prise en charge de RSpec
Prise en charge de MinItest
Async :: http :: Client
Curb (actuellement uniquement Curb :: Easy)
Em-Http-Request
Exciner
Httpclient
HTTP GEM (également connu sous le nom de http.rb)
httpx
Mantecore
Net :: http et autres bibliothèques basées sur net :: http, par exemple:
Httparty
Client de repos
Patron
Typhoeus (actuellement seulement Typhoeus :: Hydra)
IRM 2.6
IRM 2.7
IRM 3.0
IRM 3.1
IRM 3.2
IRM 3.3
Jruby
Gem Installer Webmock
ou alternativement:
# Ajouter à votre GemfileGroup: Test DO Terrain "webmock"
git clone http://github.com/bblimke/webmock.gitcd webmock Installation de râteau
Webmock 2.x a quelque peu changé depuis la version 1.x. Les modifications sont répertoriées dans Changelog.md
Créez un fichier features/support/webmock.rb
avec le contenu suivant:
nécessitent «webmock / concombre»
Ajoutez le code suivant pour test/test_helper
:
nécessitent 'webmock / minitest'
Ajoutez le code suivant à spec/spec_helper
:
nécessitent 'webmock / rspec'
Ajoutez le code suivant pour test/test_helper.rb
nécessitent 'webmock / test_unit'
Vous pouvez également utiliser WebMock en dehors d'un cadre de test:
exiger 'webmock'include webmock :: apiwebmock.enable!
Stub_Request (: Any, "www.example.com") net :: http.get ("www.example.com", "/") # ===> Succès
Stub_Request (: Post, "www.example.com"). avec (body: "ABC", en-têtes: {'Content-Length' => 3}) uri = uri.parse ("http://www.example.com/") req = net :: http :: post. new (uri.path) req ['Content-Length'] = 3res = net :: http.start (uri.host, uri.port) do | http | http.Request (req, "ABC") fin # ===> Succès
Stub_Request (: Post, "www.example.com"). avec (body: / world $ /, en-têtes: {"contenu-type" => /image/.+/}). to_return (corps: "ABC") uri = uri.parse ('http://www.example.com/') req = net :: http :: post.new (uri.path) req ['contenu-type' ] = 'image / png'res = net :: http.start (uri.host, uri.port) do | http | http.Request (req, 'Hello World') fin # ===> Succès
Stub_Request (: Post, "www.example.com"). avec (body: {data: {a: '1', b: 'cinq'}}) restclient.post ('www.example.com', "data [a] = 1 & data [b] = cinq", content_type: 'application / x-www-form-urlencoded') # ===> SuccessRestClient.post ('www.example.com', '{"data": {"a": "1", "b": "cinq"}}', content_type: 'application / json') # ===> SuccessRestClient.post ('www.example.com', '<data a = "1" b = "cinq" />', content_type: 'application / xml') # ===> Succès
Stub_Request (: Post, "www.example.com"). avec (body: hash_including ({data: {a: '1', b: 'cinq'}})) restClient.post ('www.example.com', "data [a] = 1 & data [b] = cinq & x = 1 ",: content_type => 'application / x-www-form-urlencoded') # ===> Succès
Stub_Request (: Any, "www.example.com"). avec (en-têtes: {'en-tête-name' => 'en-tête-valeur'}) uri = uri.parse ('http://www.example.com/') req = net :: http :: post.new ( uri.path) req ['head-name'] = 'header-vale'res = net :: http.start (uri.host, uri.port) do | http | http.Request (req, 'ABC') fin # ===> Succès
Stub_Request (: Get, 'www.example.com'). avec (en-têtes: {'accepter' => ['image / jpeg', 'image / png']}) req = net :: http :: get.new ("/") req ['accepter'] = [' image / png '] req.add_field (' accepter ',' image / jpeg ') net :: http.start ("www.example.com") {| http | http.Request (req)} # ===> Succès
Stub_Request (: Post, "www.example.com"). Avec {| demande | request.body == "ABC"} restclient.post ('www.example.com', 'ABC') # ===> Succès
Stub_Request (: Get, "www.example.com"). avec (Basic_Auth: ['User', 'Pass']) # ou # Stub_Request (: Get, "www.example.com"). # avec (en-têtes: {'Autorisation' => "Basic # {base64.strict_encode64 ('utilisateur: pass'). Chomp}"}) net :: http.start ('www.example.com') do | http | req = net :: http :: get.new ('/') req.basic_auth 'utilisateur', 'pass' Http.Request (req) fin # ===> Succès
stub_request(:get, "user:[email protected]")
ne correspond pas à une demande avec les informations d'identification fournies dans l'en-tête d'autorisation.Stub_Request (: Get, "utilisateur: [email protected]") restclient.get ('utilisateur: [email protected]') # ===> Succès
Stub_Request (: any, /example/)net::http.get('www.example.com ',' / ') # ===> Succès
Stub_Request (: tout, -> (uri) {true})
uri_template = Addressable :: template.new "www.example.com/{id acteur ==> Succès
uri_template = Addressable :: template.new "www.example.com/thing/{id }.json{?x,y,z} {&other* }"stub_request(:Ay, uri_template) net :: http.get ('www. example.com ', '/ ithre/5.json?x=1&y=2&z=3&anyparam=4') # ===> Succès
Stub_request (: get, "www.example.com"). avec (query: {"a" => ["b", "c"]}) restClient.get ("http://www.example.com/ ? A [] = b & a [] = c ") # ===> Succès
Stub_Request (: Get, "www.example.com"). avec (query: hash_including ({"a" => ["b", "c"]})) restClient.get ("http://www.example.com/?aorth 1 ") # ===> Succès
Stub_Request (: Get, "www.example.com"). avec (query: hash_excluding ({"a" => "b"})) restClient.get ("http://www.example.com/?a=b") # ===> faillorestClient.get ("http : //www.example.com/? A = C ") # ===> Succès
Stub_Request (: Any, "www.example.com"). to_return (corps: "ABC", statut: 200, en-têtes: {'Content-Length' => 3}) net :: http.get ("www.example.com", '/') # ===> " abc"
Définissez le type de contenu approprié pour parsed_response
de HTTPARTY.
Stub_Request (: Any, "www.example.com"). To_return Body: '{}', en-têtes: {content_type: 'application / json'}
File.open ('/ tmp / réponse_body.txt', 'w') {| f | F.puts 'ABC'} Stub_Request (: Any, "www.example.com"). to_return (body: file.new ('/ tmp / réponse_body.txt'), statut: 200) net :: http.get ('www.example.com', '/') # ===> "ABCN"
Stub_Request (: Any, "www.example.com"). to_return_json (corps: {foo: "bar"}) net :: http.get ('www.example.com', '/') # ===> "{" foo ":" bar "}"
Stub_Request (: Any, "www.example.com"). to_return (status: [500, "Erreur du serveur interne"]) req = net :: http :: get.new ("/") net :: http.start ("www.example.com") {| http | http.Request (req)}. Message # ===> "Erreur du serveur interne"
curl -is
curl -is www.example.com > /tmp/example_curl_-is_output.txt
RAW_RESPONSE_FILE = file.new ("/ tmp / example_curl_-is_output.txt")
à partir du fichier
Stub_Request (: Get, "www.example.com"). to_return (brut_response_file)
ou chaîne
Stub_Request (: Get, "www.example.com"). to_return (RAW_Response_file.read)
Stub_Request (: any, 'www.example.net'). to_return {| request | {body: request.body}} restClient.post ('www.example.net', 'ABC') # ===> "ABCN"
Stub_Request (: any, 'www.example.net'). to_return (lambda {| request | {body: request.body}}) restClient.post ('www.example.net', 'ABC') # ===> "ABCN"
curl -is
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 (corps: lambda {| request | request.body}) restClient.post ('www.example.net', 'ABC') # ===> "ABCN"
classe Myrackapp def self.call (Env) [200, {}, ["Hello"]] endendstub_request (: get, "www.example.com"). to_rack (myrackapp) restClient.post ('www.example.com') # ===> "Bonjour"
Stub_Request (: any, 'www.example.net'). to_raise (standarderror) restClient.post ('www.example.net', 'ABC') # ===> StandardError
Stub_Request (: any, 'www.example.net'). to_raise (standarderror.new ("une erreur"))
Stub_Request (: any, 'www.example.net'). to_raise ("une erreur")
Stub_Request (: any, 'www.example.net'). to_timeoutrestClient.post ('www.example.net', 'ABC') # ===> RESTCLIENT :: 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 Toutes les réponses sont utilisées, la dernière réponse sera renvoyée infinimentnet :: http.get ('www.example.com', ',' / ') # ===> "Defn"
to_return()
, to_raise()
ou to_timeout
Stub_Request (: Get, "www.example.com"). to_return ({body: "ABC"}). alors. # then () n'est qu'un sucre syntaxique to_return ({body: "def"}). alors. to_raise (myException) net :: http.get ('www.example.com', '/') # ===> "ABCN" net :: http.get ('www.example.com', '/') # ===> "Defn" net :: http.get ('www.example.com', '/') # ===> MyException soulevée
Stub_Request (: Get, "www.example.com"). to_return ({body: "ABC"}). fois (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") disposy_request_stub (Stub_get)
Webmock.allow_net_connect! Stub_Request (: tout, "www.example.com"). To_return (body: "ABC") net :: http.get ('www.example.com', '/') # ===> "ABC" net :: http.get ('www.something.com', '/') # ===> /. com ',' / ') # ===> échec
Webmock.disable_net_connect! (Allow_localhost: true) net :: http.get ('www.something.com', '/') # ===> failurenet :: http.get ('localhost: 9887', '/') # ===> Autorisé. Peut-être au sélénium?
Les demandes autorisées peuvent être spécifiées de plusieurs façons.
Avec une String
spécifiant un nom d'hôte:
Webmock.disable_net_connect! (Autoriser: 'www.example.org') restClient.get ('www.something.com', '/') # ===> faillorestClient.get (www.example.org ',' / ') # ===> ALLERDRESTCLIENT.GET (' www.example.org:8080 ',' / ') # ===> Autorisé
Avec une String
spécifiant un nom d'hôte et un port:
Webmock.disable_net_connect! (Autoriser: 'www.example.org:8080')restclient.get('www.something.com', '/') # ===> faillorestClient.get ('www.example.org', '/') # ===> faillorestClient.get ('www.example.org:8080', '/') # ===> Autorisé
Avec un Regexp
correspondant à l'uri:
Webmock.disable_net_connect! (Permettre:% r {ample.org/foo}) restClient.get ('www.example.org', '/ foo / bar') # ===> ALLORESTCLIENT.GET ('Sample.org' , '/ foo') # ===> ALLERDRESTCLIENT.GET ('Sample.org', '/ Bar') # ===> Échec
Avec un objet qui répond à #call
, recevant un objet URI
et renvoyant un booléen:
denylist = ['google.com', 'Facebook.com', 'Apple.com'] autorisé_sites = lambda {| uri | Denylist.None? {| Site | uri.host.include? (Site)}} webmock.disable_net_connect! (permettre: allowing_sites) restClient.get ('www.example.org', '/') # ===> ALLERDRESTCLIENT.get ('www.facebook. com ',' / ') # ===> faillorestClient.get (' Apple.com ',' / ') # ===> échec
Avec un Array
de tout ce qui précède:
Webmock.disable_net_connect! (Autoriser: [ lambda {| uri | uri.host.length% 2 == 0}, /ample.org/, 'bbc.co.uk',]) restClient.get ('www.example.org', '/') # ===> ALLERDRESTCLIENT.get ('bbc.co.uk', '/') # == => AllowerRestClient.get ('bbc.com', '/') # ===> allowerrestClient.get ('www.bbc.com', '/') # ===> échec
Le protocole HTTP a 3 étapes: connecter, demander et réponse (ou 4 avec clôture). La plupart des bibliothèques clients Ruby HTTP traitent la connexion comme faisant partie de l'étape de la demande, à l'exception de Net::HTTP
qui permet d'ouvrir la connexion au serveur séparément à la demande, en utilisant Net::HTTP.start
.
L'API WebMock a également été conçue avec Connect faisant partie de l'étape de demande, et elle permet uniquement les demandes de coups, et non les connexions. Lorsque Net::HTTP.start
est appelé, WebMock ne sait pas encore si une demande est couchée ou non. WebMock retarde par défaut une connexion jusqu'à ce que la demande soit invoquée, donc quand il n'y a pas de demande, Net::HTTP.start
ne fait rien. Cela signifie que WebMock brise le comportement net :: http par défaut!
Pour contourner ce problème, WebMock propose :net_http_connect_on_start
, qui peut être transmis à WebMock.allow_net_connect!
et WebMock.disable_net_connect!
Méthodes, c'est-à-dire
Webmock.allow_net_connect! (Net_http_connect_on_start: true)
Cela force WebMock Net :: Adaptateur http pour toujours se connecter sur Net::HTTP.start
. Au moment de la création de la connexion, il n'y a pas encore d'informations sur la demande ou l'URL, WebMock n'est donc pas en mesure de décider ou non d'une demande et toutes les connexions sont autorisées. Pour activer les connexions uniquement à un domaine spécifique (par exemple, votre serveur de test) utilisez:
Webmock.allow_net_connect! (Net_http_connect_on_start: "www.example.com")
exiger 'webmock / test_unit'stub_request (: tout, "www.example.com") uri = uri.parse (' http://www.example.com/ ') req = net :: http :: post.new ( uri.path) req ['Content-Length'] = 3res = net :: http.start (uri.host, uri.port) do | http | http.Request (req, 'ABC') Endassert_Requeted: Post, "http://www.example.com", En-têtes: {'Content-Length' => 3}, corps: "ABC", Times: 1 # ===> SuccessSersert_not_Request: Get, "http://www.something.com" # ===> SuccessSeusert_Requeted (: Post, "http://www.example.com", fois: 1) {| req | req.body == "ABC"}
Webmock.allow_net_connect! Net :: http.get ('www.example.com', '/') # ===> SuccessSersert_request: Get, "http://www.example.com" # ===> Succès
Stub_get = Stub_Request (: Get, "www.example.com") Stub_post = Stub_Request (: Post, "www.example.com") net :: http.get ('www.example.com', '/') ASSERT_REQUEST (Stub_get) ASSERT_NOT_REQUEST (SUB_POST)
WebMock
Ce style est emprunté à Fakeweb-Matcher
Exiger 'webMock / RSpec'Expect (webMock) .po have_request (: get, "www.example.com"). avec (body: "ABC", en-têtes: {'Content-Length' => 3}). TwiceExpect (webMock) .not_to have_request (: get, "www.something.com") attend (webmock) .po_request (:: Post, "www.example.com"). avec {| req | req.body == "ABC"} # Notez que le bloc avec `faire ... end` au lieu de supports bouclés ne fonctionnera pas! # Pourquoi? Voir ce commentaire https://github.com/bblimke/webmock/issues/174#issuecome-34908908expect(webmock).to have_request (: get, "www.example.com"). avec (query: {"a" => ["b", "c"]}) attend (webmock) .po have_request (: get, "www.example.com"). avec (query: hash_including ({"a" => ["b", "c"]})) avec (body: {"a" => ["b", "c"]}, en-têtes: {'contenu-type' => 'application / json'})
a_request
attendez (a_request (: post, "www.example.com"). avec (body: "ABC", en-têtes: {'Content-Length' => 3})). à have_been_made.onceExpect (a_request (: post, "www.something.com")). To have_been_made.times (3) attendez (a_request (: post, "www.something.com")). Pour have_been_made.at_least_onceExpect (a_request. (: Post, "www.something.com")). à have_been_made.at_least_times (3) attendre (a_request (: post, "www.something.com")). To have_been_made.at_most_twiceExpect (a_request (: post, "www.something.com")). to have_been_made.at_most_times (3 3 "). ) attendre (a_request (: tout, "www.example.com")). not_to have_been_madeexpect (a_request (: post, "www.example.com"). Avec {| req | req.body == "ABC"}) . à have_been_madeexpect (a_request (: get, "www.example.com"). avec (query: {"a" => ["b", "c"]})). à have_been_madeexpect (a_request (: get, "www.example.com"). avec (query: hash_including ({"a" => ["b", "c"]}))). To have_been_madeexpect (a_request (: post, "www.example.com"). avec (body: {"a" => ["b", "c"]}, en-têtes: {'contenu-type' => 'application / json'})). To have_been_made
Stub = Stub_Request (: Get, "www.example.com") # ... Faites des demandes ... attendez-vous (Stub) .po have_been_requeted
Si vous souhaitez réinitialiser tous les talons actuels et l'historique des demandes, utilisez WebMock.reset!
Stub_Request (: Any, "www.example.com") net :: http.get ('www.example.com', '/') # ===> successwebmock.reset! net :: http.get ('www .example.com ',' / ') # ===> FailureAssert_not_request: get, "www.example.com" # ===> Succès
Si vous souhaitez réinitialiser uniquement les compteurs des demandes exécutées, utilisez 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', '/')t ::http.get('www.example2.com', '/')expect(Stub).to have_been_request.times (2) (Stub2) .po have_been_request.Times (1) webmock.reset_executed_requests! attendre (Stub) .not_to have_been_requestExpect (Stub2) .not_to have_been_request
# Désactiver webmock (tous les adaptateurs) webmock.disable! # Désactiver webmock pour toutes les libs sauf net :: httpwebmock.disable! (Sauf: [: net_http]) # activer webmock (tous les adaptateurs) webmock.enable! # Activer webmock pour tous les libs (tous sauf patronwebmock.enable! (sauf: [: patron])
Une demande exécutée correspond à la demande Stubbed si elle passe en suivant les critères:
Lorsque la demande URI correspond à une chaîne URI de demande Stubbed, un modèle Regexp ou un modèle URI RFC 6570
Et la méthode de demande est la même que la méthode de demande Stubbed ou la méthode de demande Stubbed est: tout
Et le corps de la demande est le même que le corps de la demande ou le corps de demande de talon n'est pas spécifié
Et les en-têtes de demande correspondent aux en-têtes de demande Souchbed, ou les en-têtes de demande Souchbed correspondent à un sous-ensemble d'en-têtes de demande, ou les en-têtes de demande Stubbed ne sont pas spécifiés
Et les matchs de demande à condition que le bloc ou le bloc ne soit pas fourni
Toujours le dernier talon déclaré correspondant à la demande sera appliquée, c'est-à-dire:
Stub_request (: get, "www.example.com"). to_return (corps: "ABC") Stub_request (: get, "www.example.com"). to_return (corps: "def") net :: http.get ('www.example.com', '/') # ====> "DEF"
Webmock correspondra à toutes les différentes représentations du même URI.
C'est-à-dire que toutes les représentations suivantes de l'URI sont égales:
"www.example.com" "www.example.com/" "www.example.com:80" "www.example.com:80/" "http://www.example.com" "http: // www.example.com/""http://www.example.com:80""http://www.example.com:80/ "
Les uris suivants avec UserInfo sont également égaux pour WebMock
"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" g%20b:[email protected]:80/" tente [email protected]/ "" http: // a% 20b: [email protected]: 80 "" http: // a% 20b: [email protected]: 80 / "
ou ceux
"www.example.com/my path /? a = my param & b = c" "www.example.com/my%20path/?a=my%20param&b=c" "www.example.com:80/my path / ? a = mon param & b = c "" www.example.com:80/my%20path/?a=my%20param&b=c "" http://www.example.com/my path /? a = mon param & b = 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"
Si vous fournissez RegexP pour correspondre à URI, WebMock essaiera de le faire correspondre à chaque forme valide de la même URL.
IE /my path/
va correspondre www.example.com/my%20path
car il est équivalent de www.example.com/my path
Si vous utilisez le modèle Addressable :: pour la correspondance, WebMock reportera les règles de correspondance à l'adresse, qui est conforme à RFC 6570.
Si vous utilisez l'une des méthodes WebMock pour faire correspondre les paramètres de requête, alors l'adressable sera utilisé pour correspondre à l'uri de base et WebMock correspondra aux paramètres de requête. Si vous ne le faites pas, WebMock permettra à l'adresse corresponde à l'URI complet.
WebMock correspondra aux en-têtes de demande contre les en-têtes de demande Stubbed dans les situations suivantes:
La demande de talon a des en-têtes spécifiés et les en-têtes de demande sont les mêmes que les en-têtes Stubbed
IE Headers Stubbed: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
, demandé: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
La demande Stubbed a des en-têtes spécifiés et les en-têtes de demande Stubbed sont un sous-ensemble d'en-têtes de demande
IE Headers Stubbed: { 'Header1' => 'Value1' }
, demandé: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
La demande Stubbed n'a pas d'en-têtes
IE En-têtes Stubbed: nil
, demandée: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
Webmock normalise les en-têtes et traite toutes les formes des mêmes en-têtes que l'égalité: c'est-à-dire que les deux ensembles d'en-têtes suivants sont égaux:
{ "Header1" => "value1", content_length: 123, X_CuStOm_hEAder: :value }
{ header1: "value1", "Content-Length" => 123, "x-cuSTOM-HeAder" => "value" }
Pour enregistrer les véritables interactions HTTP de votre application et les rejouer plus tard dans les tests, vous pouvez utiliser du magnétoscope avec WebMock.
Webmock.after_request do | request_signature, réponse | met "la demande # {request_signature} a été faite et # {réponse} a été renvoyé" fin
Webmock.after_request (sauf: [: patron], real_requests_only: true) do | req_signature, réponse | met "la demande # {req_signature} a été faite et # {réponse} a été renvoyé" fin
Veuillez les soumettre ici http://github.com/bblimke/webmock/issues
Vous pouvez contribuer par des problèmes de triage qui peuvent inclure la reproduction de rapports de bogues ou demander des informations vitales, telles que les numéros de version ou les instructions de reproduction. Si vous souhaitez commencer les problèmes de triage, un moyen facile de commencer est de vous abonner à WebMock sur Codetriage.
Si vous avez des suggestions sur la façon d'améliorer WebMock, veuillez envoyer un e-mail à la liste de diffusion groupes.google.com/group/webmock-users
Je suis particulièrement intéressé par la façon dont le DSL pourrait être amélioré.
Afin de travailler sur WebMock, vous devez d'abord fourche et cloner le dépôt. Veuillez effectuer un travail sur une succursale dédiée et reprendre contre Master avant d'envoyer une demande de traction.
Les lignes initiales de ce projet ont été écrites pendant la nouvelle journée de piratage en bambou grâce à mes collègues bambinos pour toutes les grandes suggestions!
Les personnes qui ont soumis des correctifs et de nouvelles fonctionnalités ou suggéré des améliorations. Un grand merci à ces gens:
Ben Pickles
Mark Evans
Ivan Vega
Piotr usewicz
Nick Plante
Nick Quaranto
Diego E. "Flameeeyes" Pettenò
Niels meersschaert
Mack Earnhardt
Arvicco
Sergio Gil
Jeffrey Jones
Tekin Suleyman
Tom ward
Nadim Bitar
Myron Marston
Sam Phillips
Jose Angel Cortinas
Razique
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
Shterenzon romain
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 Bleyshthing
Jon Leighton
Ryan Schlesinger
Julien Boyer
Kevin Glowacz
Hans Hasselberg
Andrew France
Jonathan Hyman
Rex Feng
Pavel Forkt
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 Bladt
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 Strong
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 Gritssenko
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
pêchetand46
Franky Wahl
Vous chayoung
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 Terre
yurivm
Allonge de Mike
Charles Pence
Alexey Zapparov
Pablo Brasero
Piment cedrique
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
Déviènement de Gabe Martin
Michael Grosser
Aleksei Maridashvili
Ville Lautanala
Koichi ito
Jordan Harband
Tarmo Tänav
Joe Marty
Chris Thomson
Vít Ondruch
George Ulmer
Christof Koenig
Chung-yi chi
Olexandr Hoshylyk
Janko Marohnić
Pat Allan
Chanson de Rick
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
Boulanger gris
Soonkhen Owyong
Pavel Valena
Adam Sokolnicki
Jeff Felchner
Eike Envoyer
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
Time
Michael Fairley
Ray Zane
Aller sueyoshi
Cedric Sohrauer
Akira Matsuda
Mark Spangler
Henrik Nyh
Yoann Lecuyer
Lucas Arnaud
Marc Rohloff
inkstak
Yuki Inoue
Brandon Weaver
Josh Nichols
Ricardo Trindade
Auricon
James Brown
Kazuhiro Nishiyama
Étienne Barrié
Matt Brown
Victor Maslov
Gio Lodi
Ryan Brooks
Jacob Frautschi
Christian Schmidt
Rodrigo Argumedo
Pour une liste complète de contributeurs, vous pouvez visiter la page des contributeurs.
Merci Fakeweb! Cette bibliothèque a été inspirée par Fakeweb. J'ai importé des solutions de ce projet vers WebMock. J'ai également copié du code IE Net: adaptateur HTTP. Une fausse architecture en web ne m'a malheureusement pas permis de l'étendre facilement avec les fonctionnalités dont j'avais besoin. J'ai également préféré certaines choses pour fonctionner différemment, c'est-à-dire demander la priorité.
Copyright (C) 2009-2010 Bartosz Blimke. Voir la licence pour plus de détails.