creating mocks for controller method with Rspec in rails - unit-testing

Can someone help me create mocks for the following code. I want to add a controller method in existing controller by following name and want to test its behavior to a movie class containing title, director, rating etc as table instances. Unfortunately I am unfamiliar with BDD commands to use here.
describe MoviesController do
describe "#find_same_director" do
before :each do
fake_movies = [mock('movie1'), mock('movie2')]
end
context "with invalid attributes" do
it "flashes no such director message" do
flash[:notice].should_not be_nil
end
it "redirects to the index method" do
response.should redirect_to movies_path
end
end
context "with valid attributes" do
it "calls model method to find all movies" do
movie = Movie.find_with_director, {:director => 'George Lucas'}
get :show, id: #fake_movies
assigns(:movie).should eq(#fake_results)
end
it "renders the #find_same_director view" do
get :find_same_director, id: #fake_movies
response.should render_template :find_same_director
end
end
end
end

Are you noticing that you are trying to test different things at different test cases? (the first contexts you aren't executing the action "get :x", the last ones you are doing "get :show"
First of all you should think about the behavior of your code, so, i can think of two contexts (what kind of situations do you have in this case):
# with valid parameters(for e.g.: i should pass the right data, before this context i must create the data for the text).
# with invalid parameters(for e.g: the parameters passed to the GET request should not be existent on the system).
Then you should think about what happens when this contexts are active.
context "with valid parameters" do
it "should return the other movies of the same director, and assign it to the #movies"
it "should render the template of the #find_same_director page"
end
context "with invalid parameters" do
it "should redirect to the movies_path"
it "should put a flash message that the director is invalid"
end
After you think about the test cases do you have to think about how to implement them, i'll give you a hint:
it "should return the other movies of the same director, and assign it to the #movies" do
# THINKING ABOUT BDD HERE YOU SHOULD THINK OF THIS CODE SECTIONS AS FOLLOW:
# GIVEN ( OR THE CONDITIONS FOR THE ACTION HAPPEN)
#director = Director.new
movies = [Movie.new, Movie.new]
#director.movies = movies
# HERE ILL FIX THE VALUES SO I CAN USE IT ON MY EXPECTATIONS
Director.stub!(:find).with(#director_id).and_return(#director)
# WHEN, THE ACTION HAPPENED
get :find_same_director, :id => #director_id
# THEN THE EXPECTATIONS THAT SHOULD BE MATCHED
assigns(:movies).should == #director.movies
end
For a more real experience with tests i recommend you to watch the screencasts: http://destroyallsoftware.com/

Related

Session variable lost after redirect for feature spec

The session object is cleared after redirect during testing.
First, my test stack. I am running a Rails 4.2.4 app with capybara 2.6.2, capybara-webkit 1.8.0, and rspec 3.3.0. My tests were running without issue until, for no apparent reason whatsoever, they weren't.
Below is my code (condensed to stay on point):
assessment_controller.rb
def create
#assessment_basic = Assessment::Basic.new(params)
if #assessment_basic.valid?
session[:most_recent_zip_code] = #assessment_basic.zip_code
if household.search.present?
update_household_search(#assessment_basic.zip_code)
end
redirect_to dashboard_path
else
render :new
end
end
private
def household
if #household
#household
elsif session[:household_id]
#household = find_household(session[:household_id])
elsif session[:most_recent_zip_code]
#household = Household.create(household_params)
session[:household_id] = #household.id
end
#household
end
As you can see, this is pretty straight-forward. I am receiving a zip code in the params. I store that zip code for later use and use it to create a household object unless one already exists, in which case I return that instance. If a household object is instantiated, I then store its id in the session, return control back to the action and redirect to the dashboard_path having two variables in session. All of this works well, and has worked well for some time now.
However, when I try to access the variables in the dashboard#index action, none of the session variables I stored are present. The feature works, which suggests that my problem is with the bits running my specs. By the way, the spec passes locally. It is when the code is moved to our CI environment that we get the error. We tried three different CI environments (Circle, Semaphore, and Travis) and they all report the same error:
#<NoMethodError: undefined method 'search' for nil:NilClass>
Which basically means, the household could not be recreated and is therefore nil. A closer look shows the reason the household could not be created from session is that the session was cleared.
Can someone help me identify the component(s) involved in ensuring session values persists during tests? Let me know if you need anything else in order to be able to help me.
Hector
it 'a client visits the referrals page with all providers minus the single stop and tax locations from the dashboard page and ' do
user_visits_the_homepage
enter_zip_code('11217', true)
dashboard_page.expect_to_be_on
dashboard_page.click_browse_local_resources
referrals_page.expect_to_be_on
end
def user_visits_the_homepage
visit '/'
expect(page).to have_content t('welcome.where')
end
def enter_zip_code(zip_code = '11217', remain_dashboard = false)
within '.welcome-form:nth-of-type(1)' do
fill_in t('welcome.where'), with: zip_code
click_on t('welcome.get_started')
end
expect(page).to have_content t('header.dashboard')
click_on t('header.your_profile') unless remain_dashboard
expect(page).to have_field t('activerecord.attributes.client_household_member.zip_code'), with: zip_code unless remain_dashboard
end

param is missing or the value is empty: holiday

Hi guys new to ruby on rails, having this problem when i try to create new holiday records for a particular profile . it says error:
param is missing or the value is empty: holiday.
# Never trust parameters from the scary internet, only allow the white list through.
def holiday_params
params.require(:holiday).permit(:details, :Profile_id)
end
end
profile params:
private
# Use callbacks to share common setup or constraints between actions.
def set_profile
#profile = Profile.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def profile_params
params.require(:profile).permit(:firstname, :lastname, :work_email, :phone, :employment_type, :employment_start_date, :linkedin_profile, :nationality, :date_of_birth, :notes)
end
end
Ensure that params[:holiday] exists for whatever path you are calling for the Holiday controller.
See: param is missing or the value is empty: user rails 4

Why are there 2 kinds of controller tests in MiniTest?

I'm converting over to MiniTest from RSpec, and having a couple of difficulties doing so. I have been following some examples I have found:
class ArticlesControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:articles)
end
end
So that's a class that inherits from ActionController::TestCase, that makes sense.
But then there are other examples like this:
require 'test_helper'
describe ThingsController do
describe "#create" do
it do "valid"
login_user
post :create, { catalog: { name: "My Thing", description: "Description of my thing."}}
assert_redirected_to thing_path(Thing.last)
end
end
end
Why are these two styles different? I'm using the second example, and none of my redirects are working like they do in my dev system. Trying to get to the bottom of it.
First one is Minitest::Unit test syntax explained here
Second is more like Rspec syntax, you can use minitest-spec-rails gem for that

How to write a functional test case in rails 3.1 and unit:test

i am new to rails testing and i am using unit:test. I have an action in my controller
def save_campaign
unless params[:app_id].blank?
#app = TestApp.find(params[:app_id])
if params[:test_app]
#app.update_attributes(params[:test_app])
end
flash[:notice] = "Your Registration Process is completed"
redirect_to "/dashboard"
else
redirect_to root_path
end
end
and my test case is as following
test "should save campagin " do
assert_difference('TestApp.count', 0) do
post :save_campaign, test_app: #test_app.attributes
end
assert_redirected_to "/dashboard"
end
end
This method is a post method. While running this test, it is failing and showing me a message
"should save campagin (0.07s)
Expected response to be a redirect to http://test.host/dashboard but was a redirect to http://test.host/
/home/nouman/.rvm/gems/ruby-1.9.2-p290#global/gems/actionpack-3.1.3/lib/action_dispatch/testing/assertions/response.rb:67:in `assert_redirected_to'
My guess is that i am not giving it right assertion to check params
params[:app_id] and #app = TestApp.find(params[:app_id]).
How can i write such an assertion to check these attributes, check wether a parameter is blank. How can 1 find an object with a given id.
For functional test, you should not care about testing the model, that is in your case, you should remove:
assert_difference('TestApp.count', 0) do
..
end
What you want to know in a functional test is that if the page is loaded, redirected correctly.
In your controller, you have a condition check for params, so for each of the outcome of the check, you write a test each, that is you have to write two functional tests:
test "if app_id param is empty, #save_campaign redirect to root" do
post :save_campaign, :app_id => nil
assert_redirected_to root_path
end
test "#save_campaign" do
post :save_campaign, :app_id => app_fixture_id, :test_app => #test_app.attributes.to_params
assert_redirected_to '/dashboard'
end
The trick to prepare the post params is to use method to_params method.
Hope this help.
UPDATE: If you just want to check if params[:app_id] GET param is in the URL, you should just check for this presence instead of checking if it is blank or not:
if params[:app_id]
else
end

No route matches with valid object

Having read this:
"No route matches" error?
I'm trying to figure out if there is a gem or way to monkey patch actionpack to get around this constraint.
Basically, I'm writing specs (they run fast), and I don't understand why actionpack throws this error when being applied to an object which isn't "saved".
For two reasons:
Why is it throwing a "No route matches" when it really should be throwing something more meaningful (e.g. object must be saved before a route can be constructed, or object ID is nil). The exception seems a little obscure.
I shouldn't have to save the object at all if all I am trying to do is generate a url for that object, given the ID is populated using a factory or something similar.
This constraint makes it a pain to write fast tests, unless I'm missing something...
True, the error message is a bit obscure. Regarding your second point, you don't need to save an object to generate a URL, the helper will work just as well with a literal value.
building_path(1) # GET /buildings/1 => BuildingsController#show, params={:id=>"1"}
So in the example the object can be replaced with any value:
get :show, :id => "1"
For example, if you use rails generate scaffold Article, RSpec will build a spec like this:
def mock_article(stubs={})
(#mock_article ||= mock_model(Article).as_null_object).tap do |article|
article.stub(stubs) unless stubs.empty?
end
end
describe "GET show" do
it "assigns the requested article as #article" do
Article.stub(:find).with("37") { mock_article }
get :show, :id => "37"
assigns(:article).should be(mock_article)
end
end
which does not hit the database.