库,用于在Ruby中对HTTP请求的固执和设定期望。
http low HTTP客户端LIB级别的HTTP请求(更改HTTP库时无需更改测试)
设置和验证HTTP请求的期望
基于方法,URI,标题和身体的匹配请求
在不同表示形式(也编码和非编码表格)中对同一URI的智能匹配
在不同表示形式中对同一标头的明智匹配。
支持测试::单元
支持RSPEC
支持最大的
ASYNC :: HTTP ::客户端
路缘(目前仅Curb :: Easy)
em-http-request
Excon
httpclient
HTTP GEM(也称为http.rb)
httpx
Manticore
NET :: HTTP和其他基于NET :: HTTP的库,例如:
httparty
休息客户
赞助人
Typhoeus(目前只有Typhoeus :: Hydra)
MRI 2.6
MRI 2.7
MRI 3.0
MRI 3.1
MRI 3.2
MRI 3.3
jruby
宝石安装网络货物
或或者:
#添加到您的gemfilegroup:测试做 宝石“ Webmock”结尾
git克隆http://github.com/bblimke/webmock.gitcd webmock 耙安装
自版本1.x以来,Webmock 2.x已有所变化。更改在ChangElog.md中列出
使用以下内容创建文件features/support/webmock.rb
:
需要“ Webmock/Cucumber”
将以下代码添加到test/test_helper
:
需要“ Webmock/Minitest”
将以下代码添加到spec/spec_helper
:
需要“ Webmock/rspec”
将以下代码添加到test/test_helper.rb
需要“ Webmock/test_unit”
您还可以在测试框架外使用网络货:
需要'webmock'include webmock :: apiwebmock.enable!
stub_request(:任何“ www.example.com”)net :: http.get(“ www.example.com”,“”/“)#===>成功
stub_request(:post,“ www.example.com”)。 使用(正文:“ ABC”,标题:{'content-length'=> 3})uri = uri.parse(“ http://www.example.com/”)req = net :: http :: post。 new(uri.path)req ['content-Lengths'] = 3Res = net :: http.start(uri.host,uri.port)do | http | http.request(req,“ abc”)结束#===>成功
stub_request(:post,“ www.example.com”)。 使用(Body:/world $/,标头:{“ content-type” => /image/.+/})。 to_return(body:“ abc”)uri = uri.parse('http://www.example.com/')req = net :: http :: http :: post.new(uri.path)req ['content-type' ] ='image/png'res = net :: http.start(uri.host,uri.port)do | http | http.request(req,'Hello world')结束#===>成功
stub_request(:post,“ www.example.com”)。 使用(body:{data:{a:'1',b:'五'}})restclient.post('www.example.com',“ data [a] = 1&data [b] =五”, content_type:'application/x-www-form-urlencoded')#===> ScuccesRestClient.post('www.example.com','{“ data”:{“ a”:a“:“ 1”,“ b”: “五”}}', content_type:'application /json')#===> stactionrestclient.post('www.example.com','<data a =“ 1” b =“ fix fix” />', content_type:'application/xml')#===>成功
stub_request(:post,“ www.example.com”)。 使用(正文:hash_including({data:{a:'1',b:'五'}}))restclient.post('www.example.com',“ data [a] = 1&data [a]&data [b] = fix x =五&x = 1“,:content_type =>'application/x-www-form-urlencoded')#===>成功
stub_request(:任何“ www.example.com”)。 使用(标头:{'header-name'=>'header-value'})uri = uri.parse('http://www.example.com/')req = net :: http :: http :: http :: post.new( uri.path)req ['header-name'] ='header-value'res = net :: http.start(uri.host,uri.port)do | http | http.request(req,'abc')结束#===>成功
stub_request(:get,'www.example.com')。 使用(标头:{'cack'=> ['image/jpeg','image/png']})req = net :: http :: http :: get.new(“/”)req ['cack'] = ['' image/png'] req.add_field('Accept','image/jpeg')net :: http.start(“ www.example.com”){| http | http.request(req)}#===>成功
stub_request(:post,“ www.example.com”)。使用{|请求| request.body ==“ abc”} restclient.post('www.example.com','abc')#===>成功
stub_request(:get,“ www.example.com”)。使用(basic_auth:['user','pass'])#or#stub_request(:get,get,“ www.example.com”)。 {'授权'=>“ basic#{base64.strict_encode64('用户:pass')。chomp}”}):: http.start('www.example.com')do | http | req = net :: http :: get.new('/') req.basic_auth“用户”,“通行证” http.request(req)结束#===>成功
stub_request(:get, "user:[email protected]")
与授权标头中提供的凭据不匹配请求。stub_request(:get,“用户:[email protected]”)restclient.get('用户:[email protected]')#===>成功
stub_request(:任何,/example/) net :: http.get('www.example.com','/')#===>成功>
stub_request(:any, - >(uri){true})
uri_template = equbsebable :: template.new“ www.example.com/ {id }/"stub_request(: wand ewany,uri_template)net :: http.get('www.example.com','www.example.com','/webmock/')#= ==>成功
uri_template = 地址:: template.new“ www.example.com/thing/ {id} .json {?x,,Z} {&othertub_request(:any,uri_template)net :: http.get('www。 example.com', '/thing/5.json?x=1&y=2&z=3&anyparam=4')#===>成功
stub_request(:get,“ www.example.com”)。使用(查询:{“ a” => [b“,” c“ c”]})RESTCLIENT.get(“ http://www.example.com/) ?a [] = b&a [] = c“)#===>成功
stub_request(:get,“ www.example.com”)。 使用(查询:hash_including({“ a” => [“ b”,“ c”]}))RESTCLIENT.get(“ http://www.example.com/?a [a [a [a] 1“)#===>成功
stub_request(:get,“ www.example.com”)。 使用(查询:hash_excluding({“ a“ a” =>“ b”}))restClient.get(“ http://www.example.com/?a=b”)#=============> failURERESTCLIENT.get(“ httpp ://www.example.com/?a = c“)#===>成功
stub_request(:任何“ www.example.com”)。 to_return(正文:“ ABC”,状态:200,标题:{'content-Length'=> 3})net :: http.get(“ www.example.com”,'/'/'/')#====>>>>>>>>>>>>>>>“ ABC”
为HTTPARTY的parsed_response
设置适当的内容类型。
stub_request(:任何“ www.example.com”)。to_return主体:'{}',标题:{content_type:'application/json'}
file.open('/tmp/response_body.txt','w'){| f | f.puts'abc'} stub_request(:任何“ www.example.com”)。 to_return(body:file.new('/tmp/response_body.txt'),状态:200)net :: http.get('www.example.com','/''/')#====>“ abcn”
stub_request(:任何“ www.example.com”)。 to_return_json(body:{foo:“ bar”})net :: http.get('www.example.com','/')#===>“ {” {“ foo”:“ bar”}
stub_request(:任何“ www.example.com”)。 to_return(状态:[500,“内部服务器错误”])req = net :: http :: get.new(“/”)net :: http.start(“ www.example.com”){| http | http.request(req)}。 消息#===>“内部服务器错误”
curl -is
录制的原始响应curl -is www.example.com > /tmp/example_curl_-is_output.txt
raw_response_file = file.new(“/tmp/example_curl_-is_output.txt”)
从文件
stub_request(:get,“ www.example.com”)。to_return(raw_response_file)
或字符串
stub_request(:get,“ www.example.com”)。to_return(raw_response_file.read)
stub_request(:任何,'www.example.net')。 to_return {|请求| {body:request.body}} restclient.post('www.example.net','abc')#===>“ abcn”
stub_request(:任何,'www.example.net')。 to_return(lambda {| request | {body:request.body}})retclient.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 {|请求| file.new(“/tmp/#{request.uri.host.to_s} .txt”)}))})
stub_request(:任何,'www.example.net')。 to_return(body:lambda {| request | request.body})restclient.post('www.example.net','abc')#====>“ abcn”
上课myrackapp def self.call(env)[200,{},[“ hello”]] endendStub_request(:get,“ www.example.com”)。to_rack(myrackapp)retclient.post('www.example.com')#===>“ hello hello”
stub_request(:Any,'www.example.net')。to_raise(standardError)retClient.post('www.example.net','abc')#====> standarderror
stub_request(:任何,'www.example.net')。to_raise(standarderror.new(“一些错误”))
stub_request(:任何,'www.example.net')。to_raise(“一些错误”)
stub_request(:任何,'www.example.net')。to_timeoutrestclient.post('www.example.net','abc')#====> retsclient :: requestTime :: 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”#在使用所有响应后,最后一个响应将返回infiniteluitynet :: http.get('www.example.com',',''http.get /')#===>“ defn”
to_return()
, to_raise()
或to_timeout
声明进行多个响应stub_request(:get,“ www.example.com”)。 to_return({正文:“ abc”})。然后。 #then(then()只是句法糖 to_return({{body:“ def”})。然后。 to_raise(myException)net :: http.get('www.example.com','/')#===>“ abcn” net :: http.get('www.example.com','/') #===>“ defn” net :: http.get('www.example.com','/')#===> myException升高了
stub_request(:get,“ www.example.com”)。 to_return({正文:“ abc”})。时代(2)。 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!stub_request(:任何,“ www.example.com”)。to_return(body:“ abc”)net :: http.get('www.example.com','/''/''/''/')#=====>> “ abc” net :: http.get('www.something.com','/')#===>/。+something.+/webmock.disable_net_net_net_connect !! com','/')#===>失败
webmock.disable_net_connect!(well_localhost:true)net :: http.get('www.something.com','/')#===> failurenet :: http.get('localhost:localhost:9887','',''/') #===>允许。也许是硒?
允许的请求可以通过多种方式指定。
用String
指定主机名:
webmock.disable_net_connect!(允许:'www.example.org')restClient.get('www.something.com','/')#====> failURERESTCLIEST.GET('www.example.org' ')#===> washeRestClient.get('www.example.org:8080','/')#===>允许
用String
指定主机名和端口:
webmock.disable_net_connect!(允许:'www.example.org:8080') restclient.get('www.something.com','/''/')#==========> failureREstClient.get('www.example.org',www.example.org',www.example.org',,, '/')#===> failureRestClient.get('www.example.org:8080','/')#===>允许
与Regexp
匹配URI:
webmock.disable_net_connect!(允许:%r {ample.org/foo})retClient.get('www.example.org','/foo/bar')#====> washerestclient.get('sample.org'sample.org'sample.org' ,'/foo')#===> welleRestClient.get('sample.org','/bar')#===>失败
使用响应#call
的对象,接收URI
对象并返回一个布尔值:
denylist = ['google.com','facebook.com','apple.com'] washe_sites = lambda {| uri | denylist.none?{| site | uri.host.include?(site)}} webmock.disable_net_connect!(允许:washe_sites)restclient.get('www.example.org','/''/')#= ===> wellrestclient.get('www.facebook。 com',''/')#===> failureRestClient.get('Apple.com','/')#===>失败
带有以上任何一个Array
:
webmock.disable_net_connect!(允许:[ lambda {| uri | uri.host.length%2 == 0}, /pample.org/, 'bbc.co.uk',])restClient.get('www.example.org','/')#===> welleRestClient.get('bbc.co.uk','/')#== => washeRestClient.get('bbc.com','/')#===> welleRestClient.get('www.bbc.com','/')#===>失败
HTTP协议有3个步骤:连接,请求和响应(或4个带有关闭的)。大多数Ruby HTTP客户端库将连接视为请求步骤的一部分,除了Net::HTTP
外,它允许使用Net::HTTP.start
使用NET :: HTTP将连接与请求分开打开。
WebMock API还设计为连接是请求步骤的一部分,并且仅允许固执请求而不是连接。当Net::HTTP.start
被调用时,Webmock尚不知道请求是否是固定的。默认情况下,WebMock延迟了一个连接,直到调用请求为止,因此当没有请求时, Net::HTTP.start
不做任何事情。这意味着WebMock默认情况下会破坏NET :: HTTP行为!
为了解决此问题,WebMock提供:net_http_connect_on_start
选项,可以将其传递给WebMock.allow_net_connect!
和WebMock.disable_net_connect!
方法,即
webmock.allow_net_connect!(net_http_connect_on_start:true)
这迫使网络货物NET :: HTTP适配器始终在Net::HTTP.start
。在建立连接时,尚无有关请求或URL的信息,因此Webmock无法决定是否固态请求,并且允许所有连接。仅启用与特定域(例如测试服务器)的连接:
webmock.allow_net_connect!(net_http_connect_on_start:“ www.example.com”)
需要'webmock/test_unit'stub_request(:任何,“ www.example.com”)uri = uri = uri.parse('http://www.example.com/')req = net :: http :: http :: post.new( uri.path)req ['content-Length'] = 3Res = net :: http.start(uri.host,uri.port)do | http | http.request(req,'abc')endassert_requested:post,“ http://www.example.com”, 标题:{'content-Lengths'=> 3},正文:“ ABC”, 时间:1#===> successAssert_not_requested:get,“ http://www.something.com”#===> successAssert_requested(: 时间:1){| req | req.body ==“ ABC”}
webmock.allow_net_connect!net :: http.get('www.example.com','/')#===> successAssert_requested:get,“ http://www.example.com”#======>成功>
stub_get = stub_request(:get,“ www.example.com”)stub_post = stub_request(: (stub_get)assert_not_requested(stub_post)
WebMock
模块上的RSPEC中设置期望这种样式是从假韦伯捕捉器借来的
需要'WebMock/rspec'expect(webmock)。 使用(body:“ abc”,标题:{'content-length'=> 3})。twiceexpect(webmock).not_to hass_requested(:get,'www.something.com”)期望(webmock)。发帖,“ www.example.com”)。 使用{| req | req.body ==“ abc”}#请注意,带有'do ... end'而不是卷发括号的块无法工作!#为什么?请参阅此评论https://github.com/bblimke/webmock/issues/174#issuecomment-34908908 expect(webmock).to hass_requested(:get,“ get,” www.example.com”)。 使用(查询:{“ a” => [“ b”,“ c”]})期望(webmock)。 使用(查询:hash_including({“ a” => [“ b”,“ c”]}))期望(webmock)。 与(正文:{”
a_request
在RSPEC中设置期望期待(a_request(:post,“ www.example.com”)。 使用(正文:“ ABC”,标头:{'content-Length'=> 3}))。 to_been_made.onceexpect(a_request(:post,“ www.something.com”)。 (:post,“ www.something.com”)。 to_been_made.at_least_times(3)期望(a_request(:a_request(: )期望(a_request(:any,“ www.example.com”))。 。 to_been_madeexpect(a_request(:get,“ www.example.com”)。使用(QUERY:{“ a” => [b“,” c']}))。 to_been_madeexpect(a_request(:get,“ www.example.com”)。 使用(查询:hash_including({“ a” => [“ b”,“ c”]})))。 使用(正文:{“ a” => [“ b”,“ c”]},标题:{'content-type'=>'application/json'}))。
stub = stub_request(:get,“ www.example.com”)#...提出请求...期望(stub)。
如果要重置所有当前的存根和请求的历史记录,请使用WebMock.reset!
stub_request(:任何“ www.example.com”)net :: http.get('www.example.com','/')#===> successwebmock.reset!net!net :: http.get('wwwww 。
如果您只想重置执行请求的计数器,请使用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(expect(stub) (stub2)。
#disable webmock(所有适配器)webmock.disable!#disable webmock除net :: httpwebmock.disable!(除外:[:ext:[:net_http])#eNable webmock(all adapters)webmock.enable!除了Patronwebmock.enable!(除外:[:Patron])
执行的请求符合固定请求,如果该请求按照标准通过:
当请求时,URI匹配固定请求URI字符串,RegexP模式或RFC 6570 URI模板
和请求方法与固执请求方法或固执请求方法相同:任何
并且请求主体与未指定的固执请求主体或固执请求主体相同
并请求标头匹配固定请求标头,或固定请求标头匹配请求标头的子集,或未指定固定请求标头
并没有提供请求匹配项或块
始终将使用最后声明的存根匹配该请求,即:
stub_request(:get,“ www.example.com”)。to_return(body:“ abc”)stub_request(:get,“ www.example.com”)。to_return(body:“ def”)net :: http.get ('www.example.com','/')#====>“ def”
WebMock将匹配同一URI的所有不同表示。
即URI的所有以下表示都相等:
“ www.example.com”“ www.example.com/”“ www.example.com:80”“ www.example.com:80/”“ http://www.example.com” www.example.com/""http://www.example.com:80"“http://www.example.com:80/”
Webmock的以下URIS也与UserInfo相同
“ 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”“” :// a b:[email protected]:80/“” a%20b:[email protected]“” a%20b:[email protected]/“” a%20b:pass@a www.example.com:80"“a%20b:[email protected]:80/"ro"http://a%20b:pass@[email protected]"”“http://a%20b: [email protected]/“” http:// a%20b:[email protected]:80“” http:// a%20b:[email protected]:80/“
或这些
“ www.example.com/my path/?a =我的param&b = c”“ www.example.com/my%20path/?a=my%20param&b=c”“ www.example.com:80/my path/path/path/path/path/path/path/path ? c“” http://www.example.com/my%20path/?a=my%20param&b=c“” http://www.example.com:80/my path/?a =我的param&b = c” “ http://www.example.com:80/my%20path/?a=my%20Param&b=c”
如果您提供REGEXP匹配URI,WebMock将尝试与同一URL的每种有效形式匹配。
即/my path/
将匹配www.example.com/my%20path
,因为它等效于www.example.com/my path
如果使用可寻址::模板进行匹配,则WebMock将将匹配规则推迟到可寻址,该规则符合RFC 6570。
如果您使用任何网络货物方法来匹配查询参数,则可寻址可用于匹配uRI和WebMock的基本访问,将匹配查询参数。 如果您不这样做,那么Webmock将让可寻址匹配完整的URI。
在以下情况下,WebMock将与固执请求标头匹配请求标头:
Stubbed请求已指定标题,并且请求标头与固定的标题相同
IE固态标头: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
,请求: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
Stubbed请求已指定标题,并且固定请求标头是请求标题的子集
IE固态标头: { 'Header1' => 'Value1' }
,请求: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
Stubbed请求没有标题
IE固态标头: nil
,请求: { 'Header1' => 'Value1', 'Header2' => 'Value2' }
Webmock将标头归一化,并将所有形式的同一标题与等值相同:即以下两组标头相等:
{ "Header1" => "value1", content_length: 123, X_CuStOm_hEAder: :value }
{ header1: "value1", "Content-Length" => 123, "x-cuSTOM-HeAder" => "value" }
要记录您的应用程序的真实HTTP交互,并在以后在测试中重播它们,您可以将VCR与Webmock一起使用。
webmock.after_request do | request_signature,响应| puts“请求#{request_signature},并返回#{响应}”结束
webmock.after_request(除:[:patron],real_requests_only:true)do | req_signature,响应| puts“请求#{req_signature},并返回#{响应}”结束
请在这里提交http://github.com/bblimke/webmock/issues
您可以通过分类问题来做出贡献,这些问题可能包括复制错误报告或询问重要信息,例如版本号或复制说明。如果您想开始分类问题,那么一种开始的一种简单方法是在CodetRiage上订阅Webmock。
如果您对如何改进网络货物有任何建议,请向邮件列表组发送电子邮件。
我对如何改善DSL特别感兴趣。
为了在Webmock上工作,您首先需要分叉并克隆回购。在发送拉动请求之前,请在专用的分支上进行任何工作,并反对主人。
该项目的最初几行是在新的Bamboo Hack Day上写的,这要归功于我的Bambinos的所有好建议!
提交补丁和新功能或建议改进的人。非常感谢这些人:
本·泡菜
马克·埃文斯
伊万·维加(Ivan Vega)
piotr使用WISWICZ
尼克·普兰特
尼克·夸兰托(Nick Quaranto)
迭戈·E。
Niels Meersschaert
Mack Earnhardt
阿维科
Sergio Gil
杰弗里·琼斯
Tekin Suleyman
汤姆·沃德
纳迪姆·比塔(Nadim Bitar)
迈伦·马斯顿
山姆·菲利普斯(Sam Phillips)
Jose Angel Cortinas
razic
史蒂夫·托克(Steve Tooke)
Nathaniel Bibler
马丁·拉夫兰(Martyn Loughran)
Muness Alrubaie
查尔斯·李
瑞安·比格(Ryan Bigg)
皮特·希金斯(Pete Higgins)
汉斯·德·格拉夫(Hans de Graaff)
Alastair Brunton
山姆·斯托克斯
尤金·布尔萨科夫(Eugene Bolshakov)
詹姆斯·康罗伊·菲恩(James Conroy-Finn)
Salvador Fuentes Jr
亚历克斯·罗森伯格(Alex Rothenberg)
艾丹·费尔德曼(Aidan Feldman)
史蒂夫·赫尔
杰伊·阿德基森(Jay Adkisson)
扎克·丹尼斯(Zach Dennis)
Nikita Fedyashev
林·詹·辛(Lin Jen-Shin)
戴维·尤(David Yeu)
AndreasGarnæs
罗马shterenzon
克里斯·麦格拉思(Chris McGrath)
斯蒂芬·塞利斯(Stephen Celis)
Eugene Pimenov
阿尔伯特·洛普(Albert Llop)
克里斯托弗·皮克斯(Christopher Picklay)
Tammer Saleh
尼古拉斯·富奇(NicolasFouché)
乔·范·戴克(Joe Van Dyk)
马克·亚伯拉莫夫
弗兰克·舒马赫(Frank Schumacher)
Dimitrij Denissenko
Marnen Laibow-Koser
evgeniy dolzhenko
尼克·雷伯拉(Nick Recobra)
乔丹·埃尔弗(Jordan Elver)
Joe Karayusuf
保罗·科尔滕斯(Paul Cortens)
jugyo
副业
埃里克·奥斯特里奇(Eric Oestrich)
Erwanlr
本·布莱特(Ben Bleything)
乔恩·莱顿(Jon Leighton)
瑞安·施莱辛格(Ryan Schlesinger)
朱利安·博耶(Julien Boyer)
凯文·格洛瓦奇(Kevin Glowacz)
汉斯·哈塞尔伯格(Hans Hasselberg)
安德鲁法国
乔纳森·海曼(Jonathan Hyman)
雷克斯冯
Pavel Forkert
Jordi Massaguer PLA
杰克·贝尼洛夫(Jake Benilov)
汤姆·波瓦斯
Mokevnin Kirill
亚历克斯·格兰特(Alex Grant)
卢卡斯·多门
Bastien Vaucher
Joost Baaij
乔尔·奇宾代尔(Joel Chippindale)
Murahashi Sanemat Kenichi
蒂姆·库弗斯(Tim Kurvers)
Ilya Vassilevsky
盖特瓦特
Leif Bladt
亚历克斯·汤姆林斯(Alex Tomlins)
Mitsutaka Mimura
托米·凯拉(Tomy Kaira)
丹尼尔·范·霍瑟尔(Daniel Van Hoesel)
伊恩·阿萨夫(Ian Asaff)
Ian Lesperance
马修·霍兰(Matthew Horan)
Dmitry Gutov
弗洛里安·杜茨(FlorianDütsch)
Manuel Meurer
Brian D. Burns
莱利·斯特朗
塔米尔·杜布斯坦(Tamir Duberstein)
Stefano Uliari
亚历克斯·史特科夫(Alex Stupakov)
卡伦·王(Karen Wang)
马特·伯克(Matt Burke)
乔恩·罗(Jon Rowe)
Aleksey V. Zapparov
Praveen Arimbrathodiyil
bo牛仔裤
马修·康威
罗布·奥尔森(Rob Olson)
马克斯·林肯
Oleg Gritsenko
Hwan-Joon Choi
希巴塔·海洛西(Shibata Hiroshi)
卡莱布·汤普森(Caleb Thompson)
西奥·霍尔伯格(Theo Hultberg)
帕勃罗·贾拉拉(Pablo Jairala)
insoo嗡嗡作响的荣格
卡洛斯·阿隆索·佩雷斯(Carlos AlonsoPérez)
特洛伦兹
亚历山大·西蒙诺夫(Alexander Simonov)
ThorbjørnHermanse
马克·洛伦兹
tjsousa
Tasos Stathopoulos
丹·布特纳(Dan Buettner)
Sven Riedel
马克·洛伦兹
DávidKovács
渔夫46
弗兰基·瓦尔(Franky Wahl)
chayung you
西蒙·罗素(Simon Russell)
史蒂夫·米切尔(Steve Mitchell)
马蒂亚斯·普特曼(Mattias Putman)
Zachary Anker
伊曼纽尔·桑博(Emmanuel Sambo)
拉蒙·泰格(Ramon Tayag)
约翰内斯·施伦伯格
SiônLeRoux
马特·帕尔默
Zhao Wen
Krzysztof Rygielski
玛格土地
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)
PavelJurašek
杰克·沃思
Gabe Martin-Dempesy
迈克尔·格罗瑟(Michael Grosser)
Aleksei Maridashvili
Ville Lautanala
Koichi Ito
乔丹·哈班
塔摩塔纳夫
乔·马蒂(Joe Marty)
克里斯·汤姆森(Chris Thomson)
VítOndruch
乔治·乌尔默
克里斯托夫·科尼格(Christof Koenig)
Chung-yi Chi
Olexandr Hoshylyk
JankoMarohnić
帕特·艾伦
瑞克歌
Naruse,Yui
Piotr Boniecki
Olia Kremmyda
MichałMatyas
马特·布里克森(Matt Brictson)
肯尼·奥尔特曼(Kenny Ortmann)
redbar0n
卢卡斯·波科尼(Lukas Pokorny)
Arkadiy Tetelman
kazato sugimoto
奥尔·琼森(Olle Jonsson)
PavelRosický
Geremia taglialatela
Koichi Sasada
Yusuke Endoh
灰色贝克
很快肯·奥扬
帕维尔·瓦莱纳(Pavel Valena)
亚当·索科尔尼克(Adam Sokolnicki)
杰夫·费尔奇纳(Jeff Felchner)
eike发送
克劳迪奥·波利(Claudio Poli)
csaba apagyi
弗雷德里克·张
FábioD。Batista
Andriy Yanko
Y-YAGI
拉斐尔·弗朗萨(RafaelFrança)
乔治·克拉格霍恩(George Claghorn)
亚历克斯·詹格(Alex Junger)
Orien Madgwick
安德烈·西多罗夫(Andrei Sidorov)
马可·科斯塔(Marco Costa)
瑞安·戴维斯(Ryan Davis)
Brandur
塞缪尔·威廉姆斯
帕特里克·拉格纳森(Patrik Ragnarsson)
亚历克斯·库曼斯(Alex Coomans)
Vesa Laakso
约翰·霍索恩(John Hawthorn)
Guppy0356
Thilo Rusche
安德鲁·斯图兹(Andrew Stuntz)
卢卡斯·乌耶祖(Lucas Uyezu)
布鲁诺缝合
瑞安·克尔(Ryan Kerr)
亚当·哈伍德(Adam Harwood)
本·科希(Ben Koshy)
杰西·鲍斯(Jesse Bowes)
Marek Kasztelnik
CE07C3
江江
Oleksiy Kovyrin
马特·拉拉兹(Matt Larraz)
托尼·施耐德
NiklasHösl
约翰娜·哈特曼(Johanna Hartmann)
亚历克斯·维德拉克(Alex Vondrak)
威尔·斯托里
爱德华多·埃尔南德斯(Eduardo Hernandez)
Ojab
Giorgio Gambino
蒂米特里
迈克尔·费尔利
雷赞
去Sueyoshi
塞德里克·索赫劳尔(Cedric Sohrauer)
Akira Matsuda
马克·斯潘格勒
Henrik NYH
Yoann LeCuyer
卢卡斯·阿瑙德(Lucas Arnaud)
马克·罗洛夫(Marc Rohloff)
Inkstak
Yuki inoue
布兰登·韦弗
乔什·尼科尔斯(Josh Nichols)
Ricardo Trindade
耳thip
詹姆斯·布朗
kazuhiro nishiyama
ÉtienneBarrié
马特·布朗
维克多·马斯洛夫(Victor Maslov)
Gio Lodi
瑞安·布鲁克斯(Ryan Brooks)
雅各布·弗劳茨基(Jacob Frautschi)
克里斯蒂安·施密特(Christian Schmidt)
Rodrigo Argumedo
有关贡献者的完整列表,您可以访问贡献者页面。
谢谢假韦伯!该图书馆的灵感来自假韦伯。我将一些解决方案从该项目导入到Webmock。我还复制了一些代码IE NET:HTTP适配器。不幸的是,FakeWeb体系结构不允许我使用所需的功能轻松扩展它。我也更喜欢有些事情,以不同的方式工作,即请求存根优先级。
版权(C)2009-2010 Bartosz Blimke。有关详细信息,请参见许可证。