I'm working on an application that reaches out to a web service. I'd like to develop a proxy class that returns a fake response from the service, so I don't have to constantly be hitting it with requests while I'm developing/testing other parts of the app.
My application is expecting a response generated via Net::HTTP.
response = Net::HTTP.get(URI.parse('http://foo.com'))
case response
when Net::HTTPOK
# do something fun
when Net::HTTPUnauthorized
# you get the idea
How can I manufacture a response object, give it all the right headers, return a body string, etc?
response = ProxyClass.response_object
case response
when Net::HTTPOk
# my app doesn't know it's being lied to
Thanks.
It's actually not that hard to roll your own fake responses directly with Net::HTTP. Here's a simple 200 OK with a cookie header:
def fake_response
net_http_resp = Net::HTTPResponse.new(1.0, 200, "OK")
net_http_resp.add_field 'Set-Cookie', 'Monster'
RestClient::Response.create("Body goes here", net_http_resp, nil)
end
Since few of us are using raw Net::HTTP anymore, the (optional) last line wraps it up as a RestClient::Response, which can then be stubbed into RestClient:
stub(RestClient).post(anything) { fake_response }
I would start with FakeWeb and see if that meets your needs. If it doesn't you can probably gut whatever you need out of the internals and create your own solution.
I know this post is old, but instead of FakeWeb which seems to be largely dead, try webmock. It seems to be more full-featured and very active.
I would look into a mocking library like mocha.
Then you should be able to setup a mock object to help test:
Then following example is from Tim Stephenson's RaddOnline blog, which also includes a more complete tutorial:
def setup
#http_mock = mock('Net::HTTPResponse')
#http_mock .stubs(:code => '200', :message => "OK", :content_type => > "text/html", :body => '<title>Test</title><body>Body of the page</body>')
end
For testing a web service client, we use Sinatra, a lovely little lightweight web framework that lets you get something up and running very quickly and easily. Check out the home page; it has an entire Hello World app in 5 lines of code, and two commands to install and run the whole thing.
I ended up using a Struct.
FakeHttpResponse = Struct.new(:status, :body)
http = FakeHttpResponse.new('success', 'body goes here')
http['status'] # = 'success'
http.body # = 'body goes here'
The drawback is that .status and ['body'] are also valid, but I don't think that matters much.
I would either use FakeWeb as mentioned above, or have my rake test task start a Webrick instance to a little sinatra app which mocks the various test responses you're hoping to see.
You could look into using Rack for this which should allow you to do everything you need.
Related
I'm updating an application that was working with a very old version of RSpec (2.9.0). It works fine with 3.8, but I get a deprecation error about the following code:
response = Net::HTTPOK.new(1.0, "200", "OK")
response.stub(:content_type => 'text/json', :body => contents_raw)
Now, this code is a mock callout to an external API, and it is deep inside my code's libraries. The application I'm testing is a Sinatra app, so I'm using "get" from Rack::Test::Methods to test my app, but then deep inside the app itself is this response.stub
Apparently I should be using "double()" and "allow(object).to receive(...)", but all the examples I've seen are for using double directly in your test's "it" block, which this code is nowhere near. If I actually try to use double I just get a no method error.
WebMocks seems like a very large hammer to just replace this single call.
Maybe the right thing to do is to make a superclass of Net::HTTPOK and pass the response data in wit that superclass's new?
Huh. OK, so the wrapper class method turned out to be far easier than I expected. In my spec file I added:
class HttpWrapper < Net::HTTPOK
def initialize(data, *args)
#data = data
super(*args)
end
def content_type
'text/json'
end
def body
#data
end
end
(Bizarre detail: if I replace every instance of "data" above with "body", it explodes horribly.)
And at the block of code in question I now have:
response = HttpWrapper.new(contents_raw, 1.0, "200", "OK")
And that seems to have done the trick just fine.
If this is a terrible idea for some reason, hopefully someone will let me know. :)
the best way to mock http, use gem which called iswebmock
I'm writing a Rails app to send text messages using the Twilio API:
http://www.twilio.com/docs/api/rest/sending-sms
and to this end, I do:
client = Twilio::REST::Client.new account_sid, auth_token
client.account.sms.messages.create({
# stuff ...
})
That's all good and nice -- however, I don't want my tests to send a bunch of text messages because that would be stupid. So, I'd like to override Twilio::REST::Client.new to give me an object that'll let me call acccount.sms.messages.create in my tests without undue fuss.
I have a solution that works, but feels ugly:
def mock_twilio_service(stub_client)
Twilio::REST::Client.stub :new, stub_client do
yield
end
end
class Recordy
attr_accessor :calls
def initialize
#calls = []
end
def method_missing(method, *args)
ret = self.class.new
#calls << {
method: method,
args: args,
block_given: block_given?,
ret: ret
}
yield if block_given?
ret
end
end
and then in my test:
test "send a text" do
cli = Recordy.new
mock_twilio_service cli do
# ... stuff
end
end
I feel like I'm missing something Super Obvious, but I'm not sure. Am I? Or am I totally barking up the wrong tree? (Yes, I've looked at How do I mock a Class with Ruby? but I don't think it's quite the same...?)
Another idea would be to use WebMock. As your client is making requests to Twilio. You can just stub out the requests. Within the stub you can also define what is returned from the requests and with which parameters it can be called.
And when you set
WebMock.disable_net_connect!
it is sure that no real requests can be made from the test.
This way you don't change any behavior of your test and will not rely on an external API for your tests to pass.
Twilio evangelist here.
We wrote Test Credentials exactly for this scenario. Test Credentials are a special set of credentials (AccountSid and AuthToken) that you can use when you make requests to the Twilio REST API that tell it to basically just go through the motions of making a phone call or sending a text message, but not actually do it (or charge you for it).
You can also use a special set of phone numbers to get Twilio to return specific success or error conditions.
You can find your test credentials in your Twilio dashboard.
Hope that helps.
I am trying to mock some methods that use the google-api-ruby-client to make some testing without actually calling the api. Authentication and client and activities methods are taken from the example found on the github page (see link above), which is why I skipped it here.
The method from the example is the following:
def activities
result = client.execute(
:api_method => plus.activities.list,
:parameters => {'collection' => 'public', 'userId' => 'me'}
)
return result.data
end
I previously tried to stub the client (even chained with the execute) methods, however this results in authorization requests for oauth, which the gem uses underneath followed by mocks for the plus.activities.list methods. Is there a way to directly mock client.exectute to return something useful while skipping the whole chain?
I am not sure that I understand your problem correctly, but maybe something a little bit crazy will work
I assume that your method is in Client model so maybe something like that will work
Client.stub_chain(:client, :execute).and_return(true)
Of course if you model have different name you have to adjust. I am not sure but you can give it a try
Checkout their spec helper:
https://github.com/google/google-api-ruby-client/blob/master/spec/spec_helper.rb
And how they do the tests:
https://github.com/google/google-api-ruby-client/blob/master/spec/google/api_client_spec.rb
I'm not particularly familiar with Faraday's stubbing API, but from a casual inspection of that and the source of Balanced::Client, it looks like I'd need to be able to provide my own value for Balanced::Client.conn.
This is a step towards supporting for a stubbed connection mode by a configuration option in library, whereas flipping on that toggle, I could just use Balanced::Client.conn as a handle for stubbing whatever requests I expect to occur during my test.
It would also be super useful to have example response bodies for the various Balanced API calls and/or some builtin stub responses to use as templates for my own stubs.
Does this seem like a reasonable plan, or am I heading in the wrong direction? How do I go about doing this?
I recommend taking a look at how the unit tests for the balanced-ruby library are written. They use VCR to record and replay network calls.
While not pertinent to your exact question, you can also create one-off instances of objects by using the construct_from_response method on any object that inherits from the Resource class in resource.rb. This allows you to create a single instance of an object like so:
1.9.3p194 :034 > payload = {:name"=>"Bob", :uri=>"/v1/marketplaces/M123/accounts/fake"}
1.9.3p194 :035 > account = Balanced::Account.construct_from_response payload
1.9.3p194 :036 > account.name
=> "Bob"
Note that the uri param in the payload is required or else the library will go and try to look the object up from the server.
Can do something like this. Use the gem webmock https://github.com/bblimke/webmock
And stub requests yourself:
stub_request(:get,"https://<your secret key>:#api.balancedpayments.com/v1/customers email=#<test email>")
.with(:headers => {'Accept'=>'*/*',
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'User-Agent'=>'balanced-ruby/0.7.4'})
.to_return(:status => 200, :body => "", :headers => {})
Suppose I want to be able to write a test like this:
lambda {
do_something_involving_web_requests
}.should make(1).http_requests
It seems to me there would be several possible ways to implement this kind of functionality; however, it also seems that:
Someone might have already done so (in which case I want to look into their solution); or
Someone on StackOverflow might have an idea I haven't thought of.
So, has this been done already? And/or what are your ideas?
If you're interested in more granular testing of how your app responds to specific HTTP responses, rather than simply counting requests, you can use mocks. Here's how to use RSpec's mocks to test http requests:
#mock_http = mock("http")
Net::HTTP.stub!(:start).and_yield #mock_http
#mock_http.should_receive(:get).with("/")
One library I use is Fakeweb. Fakeweb does what #Joe mentions: it hooks into Net::HTTP and can be configured to return a canned response from a given URL. Many other HTTP libs depend on Net::HTTP so this technique has broad compatibility. Fakeweb example from its docs:
FakeWeb.register_uri(:get, "http://example.com/test1", :body => "Hello World!")
Net::HTTP.get(URI.parse("http://example.com/test1"))
=> "Hello World!"
Neither of these methods have a simple access count though, if you want that you can use rspec-mocks which has the following method count functionality (these can be used on stubs or test doubles):
double.should_receive(:msg).once
double.should_receive(:msg).twice
double.should_receive(:msg).exactly(n).times
double.should_receive(:msg).at_least(:once)
double.should_receive(:msg).at_least(:twice)
double.should_receive(:msg).at_least(n).times
double.should_receive(:msg).at_most(:once)
double.should_receive(:msg).at_most(:twice)
double.should_receive(:msg).at_most(n).times
double.should_receive(:msg).any_number_of_times