I'm currently using ruby 1.9.2 and rails 3 and I'm in the middle of rspec testing. Basically, I have a function that is called by a before filter in the application controller such that it obviously gets run every time a controller action is made anywhere on my site. For testing purposes, I'm writing tests for a different controller but my actions do not set off my before filter function call. Is there any way to specifically call functions from a specific controller within rspec tests? I can't post the code online, so no use asking for it :P.
Thanks
Inside an it or before(:each) block in a controller spec:
controller.send( :your_method_name )
And your function is going to be called.
Related
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) }.
I know integration tests are preferred but I need this to be ran in a controller test, I'm testing a gem injecting html code in the view, especially with xhr so this can't be run in a feature spec (if it can, please explain me how :) )
So with rspec controller tests you can assert a selector is present (with capybara) :
response.body.should have_selector('#foobar')
has_selector? will call the all method from capybara to find the selector.
What I want to do is get the last child of body and then assert that its id is something in particular.
AFAIK it's not possible to do this with have_selector.
What I would do is :
all('body:first-child').first.id.should == '#foobar'
However, with Capybara DSL, all is defined like this (more or less):
def all(*args)
page.all(*args)
end
And the page will be empty unless I use visit but it's for integrations specs.
How can I use capybara all method inside an rspec controller test ?
I can't test it right now but after some googling it seems like this would do the trick
def page
Capybara::Node::Simple.new(response.body)
end
Source
I set a variable inside a Controller and I'm trying to just do something as simple as read that variable in the rails console.
I thought about just doing #test in the console which is the name of the variable. but it shows as >null. When I do puts under where I set the variable it traces out the correct value in my terminal window.
Any ideas what I need to do to get to this variable via the console.
I tried putting the name of the controller first and then .variable but that threw an error
I can see what's inside my models by just using the model name and some attributes like .first and .last
You'd have to instantiate the controller and provide a public accessor to get the value in rails console.
If you're trying to debug something, I recommend you check out Pry. It's a Ruby debugging REPL. Do a require 'pry' in your controller, and put binding.pry somewhere in an action, when you execute that controller method--either interactively in a browser, or via a functional test (I recommend the latter)--it will open the Pry REPL and #test will be in scope there.
Check out this Railscast for some help using it.
Alternately, just rely on good unit or functional testing. Write a test around the method and add an assertion on assigns(:#test) to compare the value to your expectation. Check out the RSpec controller spec documentation.
Wrong use of .t method in Rails template such
<%= (user.score).t(:context => 'foo') %>
Causes an error
undefined method `t' for 46:Fixnum
The method was called on number.
Now the question is how can this situation can be tested? Where the test code should live, so all the templates will be tested before rendering?
It depends on your choice of testing framework. With the Test::Unit stuff that comes with rails your controller and integration tests render views and so should catch this sort of error. Other forms of integration testing, such as cucumber should also pick up such things.
If you use rspec then you can write view specs: specs that test view rendering in isolation.
Lastly if you find yourself with lots of logic in your views that you want to test, you're probably better off extracting that logic into a helper and writing unit tests/specs for that helper.
AFAIK you don't test the templates itself. But you can test e.g. with cucumber if you get the view results you are expecting. This could be some sort of "template testing".
I am trying to test a controller with RSpec but am having a problem because a function in the controller requires a database.
the line of code in the controller looks something like:
#myallresources = Myrsources.all
where Myresources just inherits from ActiveRecord::Base
however, because there is no database, there is nothing to load and #myallresources is just an empty array, causing the test to fail. Is there a way to connect to a database while running the rspec?
I am very new to RSpec and rails so any help would be very appreciated. Thanks.
You shouldn't use a database connection in your controller specs.
Check the section about database isolation on this page http://rspec.info/rails/writing/controllers.html
Basically you have to mock or stub your ActiveRecord models, as those should be tested separately in the models specs. Here's a simple example using mock_model:
before do
mocks = (1..3).map { mock_model(MyResource) }
MyResource.should_receive(:all).and_return(mocks)
end
Put this inside the same block where reside the describe definition testing for the actions that use MyResource.all.
You can find good explanation of mocks and stubs in following links:
http://relishapp.com/rspec/rspec-rails/v/2-5/docs/mocks/mock-model
http://relishapp.com/rspec/rspec-rails/v/2-5/docs/mocks/stub-model