I am porting an application that used RSpec successfully to test helper methods over to MiniTest. The following is the method in application_helper.rb
def active_controller?(controller_name)
params[:controller] == controller_name ? 'active' : nil
end
It is something that is used in views to help with active controller highlighting in controllers.
Below is the (not working) test for the helper.
require 'test_helper'
class ApplicationHelperTest < ActionView::TestCase
test 'active_controller? returns correct value' do
#request = ActionController::TestRequest.new
#request.params[:controller] = 'dashboard'
assert active_controller?('dashboard')
end
end
The problem is that I cant figure out how to access (or stub out) the request params to contain a controller to be able to assert the method returns true.
Any thoughts?
Try using the pry gem to see what #request, #request.params[:controller], and params[:controller] actually return.
The assertion active_controller?('dashboard') is checking 'dashboard' against params[:controller], which is currently nil, as you've only assigned #request.params[:controller] in your test.
If the test is:
test 'active_controller? returns correct value' do
params[:controller] = 'dashboard'
assert active_controller?('dashboard')
end
the assertion is comparing 'dashboard' to params[:controller], which has been assigned.
Related
Given a functional test such as:
def test_exciting_rails_upgrades
login(m=users(:manager))
post :import_users_map_fields, :csv_file => fixture_file_upload('/users.csv', 'text/csv')
assert flash.empty?
flash.discard
# other goodies omitted
end
In Rails 2.3.2 there are no errors, however in 2.3.15 the error is:
NoMethodError: undefined method `discard' for {}:Hash
/test/functional/broken_upgrades.rb:119:in `test_exciting_rails_upgrades'
Why is flash a Hash class instead of a FlashHash?
From the source it looks like both 2.3.2 and 2.3.15 ActionPack files lib/action_controller/flash.rb create the FlashHash class and inherit from Hash. However what is shown in this functional test in both 2.3.2 and 2.3.15 is a Hash class, not a HashFlash, so one cannot call discard on it.
Can anyone else reproduce this error with 2.3.15 and flash.discard?
Here are two test cases you can use to prove ActionController changes the type of 'flash' depending on whether or not it is already set.
In my app, you cannot see :index unless you're logged in, so in test_flash_is_now_a_flashhash you see that flash was set by the backend properly, while in test_flash_is_a_plain_hash it was not.
def test_flash_is_a_plain_hash
login(users(:permitted_user))
get :index
assert flash.instance_of?(Hash)
end
def test_flash_is_now_a_flashhash
get :index
assert_redirected_to :controller => "login"
assert flash.instance_of?(ActionController::Flash::FlashHash)
end
You can see this for yourself in the ActionController::TestRequest code:
def flash
session['flash'] || {}
end
Update: This has been fixed in Rails branch 2-3-stable.
I'm testing to make sure that a created user is assigned to my instance variable #user. I understand what get means, but I'm not sure what to write for the test. I'm returning with an argument error for a bad URI or URL. What's wrong with my test and how do I fix it?
it "checks #user variable assignment for creation" do
p = FactoryGirl.create(:user)
get :users
# I'm confused on what this line above means/does. What does the hash :users refer
#to
assigns[:user].should == [p]
end
The expected URI object or string error refers to get :users and the error is as follows
Failure/Error get :users
ArgumentError:
bad argument: (expected URI object or URI string)
I guess that what you want is
it "checks #user variable assignment for creation" do
p = FactoryGirl.create(:user)
get :show, id: p.id
assigns(:user).should == p
end
The line you were not sure about checks that content of the assigned variable (#user) in the show view of the user p, is equal to the p user you just created more information there
what action are you trying to test? usually, for creation, you need to test that the controller's "create" action creates a user and assigns an #user variable
I would test it this way:
describe 'POST create' do
it 'creates a user' do
params = {:user => {:name => 'xxx', :lastname => 'yyy'}}
User.should_receive(:create).with(params)
post :create
end
it 'assigns the user to an #user instance variable' do
user = mock(:user)
User.stub!(:create => user)
post :create
assigns(:user).should == user
end
end
notice that I stub/mock all user methods, since you are testing a controller you don't have to really create the user, you only test that the controller calls the desired method, the user creation is tested inside the User model spec
also, I made 2 tests (you should test only 1 thing on each it block if possible, first it test that the controller creates a user, then I test that the controller assigns the variable
I'm assuming your controller is something like this:
controller...
def create
#user = User.create(params[:user])
end
which is TOO simple, I guess you have more code and you should test that code too (validations, redirects, flash messages, etc)
I am trying to create a non ActiveRecord model in my Ruby on Rails application according to http://railscasts.com/episodes/121-non-active-record-model. I am facing hard time testing it though.
I have following class in my app/models/sms.rb file.
class Sms
def initialize
# Do stuff here
end
def deliver
# Do some stuff here
end
end
I am unable to mock deliver method on my Sms class.
it 'should do someting' do
#sms = mock(Sms)
#sms.should_receive(:deliver).and_return(true)
post :create, :user_id => #user.id
flash[:notice].should == "SMS sent successfully."
response.should redirect_to(some_url)
end
In my controller code I do have a line that says #sms.deliver. Yet above gives following error:
Failure/Error: #sms.should_receive(:deliver).and_return(true)
(Mock Sms).deliver(any args)
expected: 1 time
received: 0 times
Any pointers?
Variables beginning with # are instance variables. The #sms your controller refers to is not the same #sms as your spec has defined.
Try changing
#sms = mock(Sms)
#sms.should_receive(:deliver).and_return(true)
to
Sms.any_instance.should_receive(:deliver).and_return(true)
If your version of RSpec doesn't have the any_instance method, you'll need to stub :new on the class:
#sms = mock(Sms)
Sms.stub(:new).and_return(#sms)
#sms.should_receive(:deliver).and_return(true)
In a rails 3 app, I'm using mocha to do some mocking in my functional tests. However it doesn't seem to mock a class method in the functional controller.
Controller code
class TagsController < ApplicationController
respond_to :json
def index
response = User.tags_starting_with(params[:query])
respond_with response
end
end
Functional test
class TagsControllerTest < ActionController::TestCase
context "index action with query" do
setup do
query = "A_QUERY"
get :index, :query => query, :format => "json"
#tags = ["these", "are", "test", "tags"]
User.expects(:tags_starting_with).returns(#tags).once
end
should "return JSON formatted tags array" do
tags = JSON::parse #response.body
assert_equal #tags, tags
end
end
end
Gemfile
gem "mocha"
If I run this test, I keep running into
- expected exactly once, not yet invoked: User.tags_starting_with(any_parameters)
If I use rails console test I can mock a class method just fine, and it works as expected.
I've been through this post and have done the Gemfile, require "false" bit. But to no avail, it just doesn't want to mock the class method of the User in the controller.
Other things I've tried, if I do User.tags_starting_with("bla") in the test itself, the expectation passes.
So any ideas on why the User in the controller isn't being mocked correctly?
As said on Twitter:
You're setting you your mock after you're doing your request :-)
My create user method in the users_controller.rb looks like:
def process_login
is_login_valid(params[:user][:user_name], params[:user][:password])
if logged_in?
redirect_to root_url
else
#user = User.new(params[:user][:user_name]
redirect_to :action => 'login'
end
What I have currently:
describe UsersController do
describe "Post 'process_login'"
it "should be successful" do
post 'process_login'
response.should be_success
end
end
end
The methods is_login_valid and logged_in? are all included in the application_controller, and are methods from a ruby class I have in my /lib folder called LoginSystem.rb
My test is failing since it isn't mocking things correctly, this is my first time doing this so hoping someone can help me out.
Error message:
UsersController POST 'process_login' should be successful
Failure/Error: post 'process_login'
NoMethodError:
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
# ./app/controllers/users_controller.rb:11:in `process_login'
# ./spec/controllers/users_controller_spec.rb:21
Aah, Thanks for the error message. I'm assuming that line 11 is is_login_valid(params[:user][:user_name], params[:user][:password]).
As you're not sending any params in your test post params[:user] is nil hence the nil.[] error (when the controller is looking for params[:user][:user_name]), you set params by passing them as a hash as the 2nd parameter to post in your test.
I think you actually need
controller.stub(:logged_in?) { true }
Or if you want to test that the logged_in method is actually being called
controller.should_receive(:logged_in?).and_return(true)
The 2nd version will cause the test to fail unless the method logged_in? is called once and only once
You may also need the controller.stub(:is_login_valid} { true } as suggested by #jaydel if you're getting an error message about this method being missing as well
I believe:
controller.stub(:is_login_valid} { true }
should get you where you want to go, if I understand correctly.