How do you test the params hash in a Rails test? - ruby-on-rails

The following generates an error: "undefined local variable or method `params'"
assert_equal params[:recipient_id], users(:one).id
How do you test the params hash?
Also, how do you test assert_redirect when there are params present? The params are appended to the URL, so testing for model_path or similar fails.
Working with built in test class in Rails 3.

http://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers gives some of this information.
In this case, params is attached to the #request or #response object (depending on what HTTP method you are testing), so you can refer to it as #request.params[:recipient_id].
For redirect:
assert_redirected_to post_path(assigns(:post)) will assert that you are redirected to the proper path for a given model. The assigns method should have the instance variables you are setting inside of the controller to pass to the view

Related

RSpec Controller test converting hash into String

I have a controller spec for my application, which tests the create method on a controller. The create action actually works fine, but the spec is failing. It seems that it is auto converting the the hash POST param into a string.
let(:coupon) { attributes_for(:coupon) }
describe 'POST #create' do
it 'should create a new coupon from params' do
expect {
post :create, :coupon => coupon
}.to change(Coupon, :count).by(1)
end
end
Now, If I do puts coupon it is generating a valid hash of data, and the type is hash. For some reason the controller is receiving a string for params[:coupon]. Only in rspec testing does this happen, when I test in the browse with a POST form it works perfectly fine.
Rspec throws the following message:
NoMethodError:
undefined method `permit' for #<String:0x00000005062700>
Did you mean? print
and if I do puts params[:coupon].class in the controller in rspec it gives me String. Why might it be converting my hash into a string for the POST request, and how can I prevent this ?
I am using Rails 5.0.0 and rspec 3.5.1
This exact same behavior showed up for me recently when testing a JSON API endpoint. Originally I had this as my subject:
subject { put :my_endpoint, **input_args }
and an integer value in input_args was getting translated into a string. The fix was to add format: 'json' as an additional keyword argument to put:
subject { put :my_endpoint, **input_args, format: 'json' }
It seems that it was an issue with the gem open_taobao somehow transforming my post requests in tests.

How to write model test for SOAP request

I've written a model method that checks the validity of a VAT number using the EU's VIES system (How to use SOAP service with xml in Rails (EU VAT number check)). This works in development.
Now I'm trying to write a model test to see if the model method is able to get a response from that system:
test "test check_valid" do
#organization.number = "TESTVATNUMBER" # In def setup, #organization receives all the other relevant variables
#organization.save
#organization.check_vat # Calls upon the model method
assert ??? # How to test that the previous line/method has indeed returned the value 'false' to the controller?
end
How to complete this test? That is, how to test that check_vat worked correctly and returned the value 'false' to the controller method?
These attempts below produced the error undefined method 'assert_response' for #<OrganizationTest:0x00000007686918>:
#organization.check_validity_vat_nr
assert_response :success
assert_response 'false' do
#organization.check_validity_vat_nr
end

testing a method's parameter

How can I test a method's parameter?
def create_person child
end
Above code is my method. It takes a parameter named "child". I try to test this parameter. So, if method doesn't take parameter, test will give me error. I use minitest and Ruby on Rails.
You can use assert_raises to test if an ArgumentError is raised
assert_raises ArgumentError do
YourClass.create_person
end

Rspec controller test - how to pass arguments to a method I'm testing

I want to test this method in my controller.
def fetch_match_displayed_count(params)
match_count = 0
params.each do |param|
match_count += 1 if param[1]["result"] && param[1]["result"] != "result"
end
match_count
end
This is the test I've written so far.
describe "fetch_match_displayed_count" do
it "should assign match_count with correct number of matches" do
params = {"result_1"=>{"match_id"=>"975", "result"=>"not_match"}, "result_2"=>{"match_id"=>"976", "result"=>"match"}, "result_3"=>{"match_id"=>"977", "result"=>"not_sure"}, "result_4"=>{"match_id"=>"978", "result"=>"match"}, "result_5"=>{"match_id"=>"979", "result"=>"not_match"}, "workerId"=>"123", "hitId"=>"", "assignmentId"=>"", "controller"=>"mt_results", "action"=>"create"}
controller.should_receive(:fetch_match_displayed_count).with(params)
get :fetch_match_displayed_count, {params:params}
assigns(:match_count).should == 5
end
end
My problem seems to lie in this line get :fetch_match_displayed_count, {params:params}
The method is expecting params, but is getting nil.
I have two questions.
Should this method be in a helper and not in the controller itself (per Rails convention)?
How do I submit a get request and pass params in my test?
As a general rule, you should test the public interface of your class. For a controller, this means you test actions, not helper methods.
You should be able to make this work by setting up one or more separate test cases that call the appropriate action(s), then use a message expectation to test that the helper method is called with the right arguments -- or test that the helper method does what it is supposed to do (sets the right instance variables/redirects/etc).

How to test cookies.permanent.signed in Rails 3

I have a action in some controller that set some value in a permanent signed cookie like this:
def some_action
cookies.permanent.signed[:cookie_name] = "somevalue"
end
And in some functional test, I'm trying to test if the cookie was set correctly suing this:
test "test cookies" do
assert_equal "somevalue", cookies.permanent.signed[:cookie_name]
end
However, when I run the test, I got the following error:
NoMethodError: undefined method `permanent' for #
If I try only:
test "test cookies" do
assert_equal "somevalue", cookies.signed[:cookie_name]
end
I get:
NoMethodError: undefined method `signed' for #
How to test signed cookies in Rails 3?
I came across this question while Googling for a solution to a similar issue, so I'll post here. I was hoping to set a signed cookie in Rspec before testing a controller action. The following worked:
jar = ActionDispatch::Cookies::CookieJar.build(#request)
jar.signed[:some_key] = "some value"
#request.cookies['some_key'] = jar[:some_key]
get :show ...
Note that the following didn't work:
# didn't work; the controller didn't see the signed cookie
#request.cookie_jar.signed[:some_key] = "some value"
get :show ...
In rails 3's ActionControlller::TestCase, you can set signed permanent cookies in the request object like so -
#request.cookies.permanent.signed[:foo] = "bar"
And the returned signed cookies from an action taken in a controller can be tested by doing this
test "do something" do
get :index # or whatever
jar = #request.cookie_jar
jar.signed[:foo] = "bar"
assert_equal jar[:foo], #response.cookies['foo'] #should both be some enc of 'bar'
end
Note that we need to set signed cookie jar.signed[:foo], but read unsigned cookie jar[:foo]. Only then we get the encrypted value of cookie, needed for comparison in assert_equal.
After looking at the Rails code that handles this I created a test helper for this:
def cookies_signed(name, opts={})
verifier = ActiveSupport::MessageVerifier.new(request.env["action_dispatch.secret_token".freeze])
if opts[:value]
#request.cookies[name] = verifier.generate(opts[:value])
else
verifier.verify(cookies[name])
end
end
Add this to test_help.rb, then you can set a signed cookie with:
cookies_signed(:foo, :value => 'bar')
And read it with:
cookies_signed(:foo)
A bit hackish maybe, but it does the job for me.
The problem (at least on the surface) is that in the context of a functional test (ActionController::TestCase), the "cookies" object is a Hash, whereas when you work with the controllers, it's a ActionDispatch::Cookies::CookieJar object. So we need to convert it to a CookieJar object so that we can use the "signed" method on it to convert it to a SignedCookieJar.
You can put the following into your functional tests (after a get request) to convert cookies from a Hash to a CookieJar object
#request.cookies.merge!(cookies)
cookies = ActionDispatch::Cookies::CookieJar.build(#request)
The problem also appears to be your tests.
Here is some code and tests I used to TDD the situation where you want to set a cookie's value from passing a params value into a view.
Functional Test:
test "reference get set in cookie when visiting the site" do
get :index, {:reference => "121212"}
refute_nil cookies["reference"]
end
SomeController:
before_filter :get_reference_code
ApplicationController:
def get_reference_code
cookies.signed[:reference] ||= params[:reference]
end
Notice that the refute_nil line, the cookies is a string... that is one thing that also made this test not pass, was putting a symbol in cookies[:reference] the test did not like that, so i didn't do that.

Resources