How can I optionally mock geocoder? - ruby-on-rails

I'd like to be able to mock the results of the geocoder gem in some of my tests.
I use RSpec and Cucumber. In cucumber I'd like to default to mocking the Geocoder results, but be able to turn it back on again by adding a tag. That would be perfect! Something similar for RSpec would be good too. It would speed up my tests enormously.
I know there are some gems out there for doing similar things, e.g. sunspot_test for sunspot. Is there anything similar for geocoder?

You can use mocha to stub and mock calls. If you do something like (and I'm just making this up because I don't know the GeoCoder syntax):
GeoCoder.get_data(x, y)
And that's something you want to stub out and force to return something else, mocha allows you to do:
GeoCoder.stubs(:get_data).with(x, y).returns(my_own_variable)
And that will make any call to GeoCode.get_data, when passed in x and y, to return your custom variable. However, this stub will last for all subsequent calls during your test, so you can unstub it by calling:
GeoCoder.unstub(:get_data)
And that completely restores that method to normal.
In terms of Rspec, in a teardown block you can unstub. In terms of Cucumber, you can add a tag like #stubs_geocoder before scenarios, and within features/support/env.rb you can add this:
Before('#stubs_geocoder') do
# add your stub calls
end
After('#stubs_geocoder') do
# unstub
end

Im using vcr gem for remote services, check it out! It can be very useful in your situation. github.com/myronmarston/vcr

Related

Is there a better way to test that a script is being called in a controller other than expect_any_instance_of(#{ControllerClass}).to receive?

I'm fairly new to using RSpec, so there's a lot I still don't know. I'm currently working on speccing out a section of functionality which is supposed to run a script when a button is pressed. The script is currently called in a controller, which I don't know if there's a good way to test.
I'm currently using
expect_any_instance_of(ConfigurationsController)
.to receive(:system)
.with('sh bin/resque/kill_resque_workers')
.and_return(true)
in a feature spec and it works, but rubocop is complaining about using expect_any_instance_of and I've been told to only use that method if there was no better way.
Is there any better way to test this? Like is there a way to get the instance of the controller being used, or a better kind of test for this?
A better pattern would be to not inline the system call in your controller in the first place. Instead create a seperate object that knows how to kill your worker processes and call that from your controller. The service object pattern is often used for this. It makes it much easier to stub/spy/mock the dependency and make sure it stops at your application boundry.
It also lets you test the object in isolation. Testing plain old ruby objects is really easy. Testing controllers is not.
module WorkerHandler
def self.kill_all
system 'sh bin/resque/kill_resque_workers'
end
end
# in your test
expect(WorkerHandler).to receive(:kill_all)
If your service object method runs on instances of a class you can use stub_const to stub out the new method so that it returns mocks/spies.
Another more novel solution is dependency injection via Rack middleware. You just write a piece of middleware that injects your object into env. env is the state variable thats passed all the way down the middleware stack to your application. This is how Warden for example works. You can pass env along in your spec when you make the http calls to your controller or use before { session.env('foo.bar', baz) }.

Outputting HTTP request/response data with RSpec

I have a rails project that serves a JSON API with tests written in RSpec. Often when running specs (request specs, specifically), I’m interested in seeing some details about the HTTP request/response...i.e. the request URL, request body, and response body, ideally JSON pretty-formatted for readability. This isn't for the purposes of documentation but rather as part of the development / debugging process.
I have a helper method I wrote which does this...you just drop a method call into your spec and it prints this stuff out.
But, seems like it would be better if there was a switch that’s part of the running specs. RSpec has custom formatters which I thought might be the right direction, but in trying to build one, I can't figure out how to get access to the request/response objects like you can from inside of your spec.
How can I access the request/response objects in my custom RSpec formatter? Or, perhaps another way to approach the problem?
Here's an approach:
Assuming a rails project, in spec_helper.rb, define a global "after" hook like so:
config.after(:each) do #runs after each example
if ENV['PRINTHTTP']
#use request/response objects here, e.g. puts response.status
end
end
Then, you can conditionally enable by adding the environmental variable on the command-line:
$ PRINTHTTP=1 rspec

Testing if a function is called using Mocha

In my current Rails 3 app, I'm doing some unit testing to make sure that calls to update S3 are only done under certain situations. I don't want to update S3 during tests, so I'm using Mocha to stub out the behaviour. Is there a way to make sure a function is called using mocha? I've taken a look at Expectations, and unless I'm doing it wrong, it seems I have to do:
object.expects(:function_name).once
However, this does not yield the desired results: This will flag an error if function_name is called twice(which is desired), it will NOT flag an error if it is only called once(as it should), but the problem is it WILL NOT flag an error if the function is called zero times. I need a way to make sure it is called. It seems like mocha should support this, so maybe I'm doing it wrong. Any help would be greatly appreciated.
***** CORRECTION:
Turns out that I was doing it right, except that the mocha_verify method wasn't being called automatically. For anyone who is having a similar problem, check out Ole Morten Amundsen's answer over here: Mocha Mock Carries To Another Test
or just
object.expects(:function_name).twice
alternatively, if it has differnet input you should test that
resultmock = mock
object.expects(:function_name).with(someobject).returns(mock)
resultmock.expects(:something).returns(true)
object.expects(:function_name).with(resultmock)
don't know if this helps, but it should give you a kick start. FYI: 'once' is default. Good luck, do TDD (=test-first) or mocking will be a pain :)
Be sure to load mocha last, so it is really being loaded, as in my answer here:
Mocha Mock Carries To Another Test
Try:
object.expects(:function_name).at_least_once
Have a look at the docs: http://mocha.rubyforge.org/classes/Mocha/Expectation.html#M000042

How can I see what actually happens when a Test::Unit test runs?

In a Rails application I have a Test::Unit functional test that's failing, but the output on the console isn't telling me much.
How can I view the request, the response, the flash, the session, the variables set, and so on?
Is there something like...
rake test specific_test_file --verbose
You can add puts statements to your test case as suggested, or add calls to Rails.logger.debug() to your application code and watch your log/development.log to trace through what's happening.
In your test you have access to a bunch of resources you can user to debug your test.
p #request
p #response
p #controller
p flash
p cookie
p session
Also, remember that your action should be as simple as possibile and all the specific action execution should be tested by single Unit test.
Functional test should be reserved to the the overall action execution.
What does it mean in practice? If something doesn't work in your action, and your action calls 3 Model methods, you should be able to easily isolate the problem just looking at the unit tests. If one (or more) unit test fails, then you know which method is the guilty.
If all the unit tests pass, then the problem is the action itself but it should be quite easy to debug since you already tested the methods separately.
in the failing test use p #request etc. its ugly, but it can work
An answer to a separate question suggested
rake test TESTOPTS=-v
The slick way is to use pry and pry-nav gems. Be sure to include them in your test gem group. I use them in the development group as well. The great thing about pry and pry nav is you can step through your code with a console, so you can not only see the code as it's executed, but you can also enter console commands during the test.
You just enter binding.pry in the places in the code you want to trigger the console. Then using the 'step' command, you can move line by line through the code as it's executed.

In rails, how do you stub the render method in functional tests?

I'm writing some functional tests for a controller in rails, using mocha to do mocking/stubbing.
Is there a way to prevent the template from being rendered during the test, so that I can test only the code in the controller?
It looks like rspec provides something like this, but I'm not using rspec.
The most obvious solution seems to work:
#controller.expects(:render)
I could have sworn that I tried that last night with no luck. But this morning it works like a charm. I must have overlooked a typo.
It doesn't look like using stub is necessary here. If you want to make sure that a given template is rendered, use assert_template and/or assert_response. You can also assert a state of the response object, either by hand or using helpers like assert_select.
Would render_to_string do what you need?

Resources