I'm beginning with Rails and currently I got stuck on integration testing of controllers.
I'm trying to validate that if certain values are provided by a user in a form, Active Record generates errors and these errors are passed to a view.
My problem is that I have no idea how to access controller assigned variables (for example - #user) inside integration tests. As I read in http://guides.rubyonrails.org/testing.html#what-to-include-in-your-functional-tests I can access variables such as #controller, #request, #response but I was also expecting that I can easily access variables assigned by controller.
Unfortunately things such as:
* #user
* #controller.user
don't really work :-/
Rails Version < 5.0
You can access these variables using assigns method with symbol of variable name as a perameter. In example:
assigns(:user)
Gives you value of #user from your controller.
Rails Version > 5.0
In rails 5.0 assigns and assert_template has been_depracted, so in order to use it as before you need to add:
gem 'rails-controller-testing'
to your Gemfile.
Original discussion why using assigns is a bad idea.
If you want to verify that a certain variable has been assigned in your tests then you can use following statement in your test. This will check whether your #user variable in controller has some value in it or not.If #user has some value in it then the test will pass otherwise it will fail
assert_not_nil assigns(:user)
And then you can run following command to run your test in terminal
ruby -I test test/integration/your_test_file_name.rb -n test_name
Related
Recently started a new job, no ruby/rails experience before this gig so bare with me.
Currently I have a method defined in my application controller which has a few instance variables defined, and is being called :before_action do_something_on_start
There is an instance variable that grabs an entry from our database and I set some instance variables that will be available in the view
def do_something_on_start
#test = User.find_by(id: 1)
#enabled = #test.value == "true"
#start_date = #test.start_date
end
When running our suite of test specs, most of the feature specs come back with undefined method `value' for nil:NilClass
Not entirely sure why this is happening. Are the instance variables not available to the test spec when they run? Or do I have to have those same instance variables defined in all of our feature specs to work?
The error message is telling you that #test is nil, which means your DB doesn't contain a User with id 1. Generally test data is reset between each test, so that tests are isolated and order independent. Because of that you need to look at how you're setting up your test data either via fixtures, as mentioned by #arieljuod, or via factories using something like FactoryBot.
I've been following a rails tutorial and got to know the assigns method of Rspec.
This is how it's being used in an integration test:
class SomeTest < ActionDispatch::IntegrationTest
test "simplified test" do
get '/some/path'
#some assertions
get '/other/path'
assert_equal 'changed', assigns(:some_variable)
end
end
Assigns seem to access the controller/view of the last call.
Is that so? how does assigns get to the instance variable some_variable?
It seems to imply there is some state being preserved in the integration test that is accessed from assigns.
It turned out that Rails treat Integration tests pretty much like functional ones, so the instance variables described in the documentation for the latter works in the former. In integration tests these variables tend to be overwritten, so you'll access the state prior to your call.
That means that in an integration test you may access:
#controller: the last controller being invoked
#request: the last request sent
#response: the last response object returned
assings just wraps the access to #controller.view_assigns where all the instance variables that will be available for the view are held.
the above code works when I just run it with ruby
but when I run it in my rails app I get the above error
Well, actually it seems like your #user object has been set before. Maybe you have set it within some before_filter?
The assignment using ||= only reads the file when #user is nil, otherwise, it will ignore the assignment at all.
I'm having an issue with my specs. I'm trying to run a spec that creates and destroys an associated object, but none of my specs are creating or destroying that object. The weird thing is, I can literally copy and paste every line of code (except for the .should) out of each test into the console and the console will run each expectation perfectly, creating and destroying those objects. Here's a sample:
it "should not destroy notification for like on comment" do
comment = FactoryGirl.create(:comment)
like = FactoryGirl.create_list(:like, 2, likable: comment)
like.first.destroy
note = comment.user.notifications.find_by(notifiable: comment, from_comment: false)
note.should_not be_nil
end
Only the first like on a specific comment will send a notification to that comment's author. And if a comment only has one like, and that like is destroyed, it will destroy the notification it had originally sent, but it won't destroy the notification if the comment has more than 0 likes at any time.
Is the problem that I'm just not writing scalable code? I know my specs probably aren't perfect, but why is the console getting different results with identical input?
Are you running your rails console in test environment or in development as it defaults to?
Different database and environment configurations might be the reason for different behavior, also the note object might already exist in development db at the time you test it manually in console.
Either try running console in test environment:
$ rails c test
or better temporarily put debugger line inside your test code (you will need get 'debugger' gem installed if don't have it already):
it "should not destroy notification for like on comment" do
comment = FactoryGirl.create(:comment)
like = FactoryGirl.create_list(:like, 2, likable: comment)
debugger
like.first.destroy
note = comment.user.notifications.find_by(notifiable: comment, from_comment: false)
note.should_not be_nil
end
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.