2012-12-07 79 views
4

是的,我知道這是最好用webmock,但我想知道如何嘲笑在RSpec的這個方法:如何模擬Net :: HTTP :: Post?

def method_to_test 
    url = URI.parse uri 
    req = Net::HTTP::Post.new url.path 
    res = Net::HTTP.start(url.host, url.port) do |http| 
    http.request req, foo: 1 
    end 
    res 
end 

這裏是RSpec的:

let(:uri) { 'http://example.com' } 

specify 'HTTP call' do 
    http = mock :http 
    Net::HTTP.stub!(:start).and_yield http 
    http.should_receive(:request).with(Net::HTTP::Post.new(uri), foo: 1) 
    .and_return 202 
    method_to_test.should == 202 
end 

測試失敗,因爲with似乎試圖以匹配的Net :: HTTP :: Post對象:

RSpec::Mocks::MockExpectationError: (Mock :http).request(#<Net::HTTP::Post POST>, {:foo=>"1"}) 
expected: 1 time 
received: 0 times 

Mock :http received :request with unexpected arguments 
    expected: (#<Net::HTTP::Post POST>, {:foo=>"1"}) 
      got: (#<Net::HTTP::Post POST>, {:foo=>"1"}) 

如何搭配得當?

回答

4

如果你不關心具體的實例,你可以使用an_instance_of方法:

http.should_receive(:request).with(an_instance_of(Net::HTTP::Post), foo: 1) 
.and_return 202 
2

這是新的語法:

before do 
    http = double 
    allow(Net::HTTP).to receive(:start).and_yield http 
    allow(http).to \ 
    receive(:request).with(an_instance_of(Net::HTTP::Get)) 
     .and_return(Net::HTTPResponse) 
end 

再例如:

it "http" do 
    allow(Net::HTTPResponse).to receive(:body) 
    .and_return('the actual body of response') 
    # here execute request 
end 

如果您需要測試外部api庫,非常有幫助。