I am creating a set of tests with two factories, see below:
spec/factories/page.rb
FactoryGirl.define do
factory :page do
title "Example Title"
content "Here is some sample content"
published_on "2013-06-02 02:28:12"
end
factory :page_invalid do
title ""
content ""
published_on "2013-06-02 02:28:12"
end
end
However, in spec/controllers/page_controller_spec.rb, the following test throws an error:
describe "with invalid params" do
it "does not save the new page in the database" do
expect {
post :create, {page: attributes_for(:page_invalid)}, valid_session
}.to_not change(Page, :count).by(1)
end
The error:
1) Api::PagesController POST create with invalid params does not save the new page in the database
Failure/Error: post :create, {page: attributes_for(:page_invalid)}, valid_session
NameError:
uninitialized constant PageInvalid
# ./spec/controllers/pages_controller_spec.rb:78:in `block (5 levels) in <top (required)>'
# ./spec/controllers/pages_controller_spec.rb:77:in `block (4 levels) in <top (required)>'
This code is analogous to code in Everyday Rails Rspec so I'm not sure why the page_invalid factory isn't being recognized.
Try this:
FactoryGirl.define do
factory :page do
title "Example Title"
content "Here is some sample content"
published_on "2013-06-02 02:28:12"
end
factory :page_invalid, :class => "Page" do
title ""
content ""
published_on "2013-06-02 02:28:12"
end
end
Notice the :class => option on your :page_invalid factory.
Related
I'm having problems with FactoryGirl, I'm using sequence to avoid duplicating fields, but validations are failing anyway.
Output:
1) CustomersController anonymous user GET #edit is redirected to signin when accessing edit form
Failure/Error: get :edit, id: create(:customer)
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken, Email has already been taken
# ./spec/controllers/customers_controller_spec.rb:25:in `block (4 levels) in <top (required)>'
# -e:1:in `<main>'
3) Customer public class methods executes its methods correctly #find_by_id_or_name finds customer by name
Failure/Error: let(:john) {create(:customer, name: 'John Doe X')}
ActiveRecord::RecordInvalid:
Validation failed: Email has already been taken, Email has already been taken
# ./spec/models/customer_spec.rb:25:in `block (3 levels) in <top (required)>'
# ./spec/models/customer_spec.rb:38:in `block (5 levels) in <top (required)>'
# -e:1:in `<main>'
Factories:
FactoryGirl.define do
factory :customer do
user
name {Faker::Name.name}
sequence(:mail) { |n| "person#{n}#example.com" }
address {Faker::Address.street_address}
phone {Faker::PhoneNumber.phone_number}
end
end
FactoryGirl.define do
factory :user do
sequence(:email) {|i| "example#{i}#example.com"}
password {Faker::Internet.password(10)}
end
end
These are the tests that are failing:
RSpec.describe Customer, type: :model do
describe "public class methods" do
let(:john) {create(:customer, name: 'John Doe X')}
let(:frank) {create(:customer)}
context "responds to its methods" do
it "responds to #find_by_id_or_name" do
expect(Customer).to respond_to(:find_by_id_or_name)
end
end
context "executes its methods correctly" do
context "#find_by_id_or_name" do
it "finds customer by name" do
customer = Customer.find_by_id_or_name('John Doe X')
expect(customer).to eq john
end
it "finds customer by id" do
customer = Customer.find_by_id_or_name(frank.id)
expect(customer).to eq frank
end
end
end
end
end
RSpec.describe CustomersController, type: :controller do
context "signed in user" do
before :each do
#user = create(:user)
end
describe "GET #edit" do
it "renders :edit view" do
get :edit, id: create(:customer).id
expect(response).to render_template(:edit)
end
end
describe "DELETE #destroy" do
before :each do
#customer = create(:customer, user: #user)
end
it "deletes record" do
expect {delete :destroy, id: #customer.id}.to change(Customer, :count).by(-1)
end
end
end
end
This is happening to me all over my app. I just copied some tests that apply to Customer.
Thanks
My problem was related to not appropiately configuring database_cleaner. The configuration in this post solves the problem: How can I clean my database between erroneous rspec specs?
I have problem with testing my controller. I've test post request in 2 context. With valid attributes and with invalid attributes. I have problem with valid attributes context.
I have the following test:
describe "POST #create" do
context "with valid attributes" do
it "saves the new car_configuration in the database" do
expect{
post :create, car_configuration: attributes_for(:car_configuration)
}.to change(CarConfiguration, :count).by(1)
end
it "redirects to the index car_configuration" do
post :create, car_configuration: attributes_for(:car_configuration)
should redirect_to admin_car_configurations_url
end
end
end
And my car_configuration factory is:
FactoryGirl.define do
factory :car_configuration do
sequence(:image) {|n| "Image #{n}"}
small_cases_count 5
big_cases_count 2
association :body_style, factory: :car_body_style
association :model, factory: :car_model
association :car_class
end
end
And errors that rspec shows:
1) Admin::CarConfigurationsController POST #create with valid attributes saves the new car_configuration in the database
Failure/Error: expect{
count should have been changed by 1, but was changed by 0
# ./spec/controllers/admin/car_configurations_controller_spec.rb:42:in `block (4 levels) in <top (required)>'
2) Admin::CarConfigurationsController POST #create with valid attributes redirects to the index car_configuration
Failure/Error: should redirect_to admin_car_configurations_url
Expected response to be a <redirect>, but was <200>
# ./spec/controllers/admin/car_configurations_controller_spec.rb:49:in `block (4 levels) in <top (required)>'
spec/controllers/admin/car_configuratoins_controller_spec.rb
require 'spec_helper'
describe Admin::CarConfigurationsController do
let(:configuration) { build :configuration }
context "POST create" do
it "creates a config" do
expect { perform }.to change(CarConfiguration, :count).by(1)
end
def perform
post :create, car_configuration: configuration.attributes
end
end
end
I try to pass these two create controller specs but for some reason it it not validating the Item object. Could it be that FactoryGirl.attributes_for(:item) are missing the profile and attachment required associations? If so, how can I pass it to attributes too?
describe "POST #create" do
context "signed in" do
login_user
context "with valid attributes" do
it "creates a new item" do
expect{
post :create, trend: FactoryGirl.attributes_for(:item)
}.to change(Item,:count).by(1)
end
it "redirects to the home page" do
post :create, item: FactoryGirl.attributes_for(:item)
response.should redirect_to Item.last
end
end
end
I got these errors
Failures:
1) ItemsController POST #create signed in with valid attributes creates a new item
Failure/Error: expect{
count should have been changed by 1, but was changed by 0
# ./spec/controllers/items_controller_spec.rb:42:in `block (5 levels) in <top (required)>'
2) ItemsController POST #create signed in with valid attributes redirects to the home page
Failure/Error: response.should redirect_to Item.last
Expected response to be a <redirect>, but was <200>
# ./spec/controllers/items_controller_spec.rb:48:in `block (5 levels) in <top (required)>'
This is the Item factory
FactoryGirl.define do
factory :item do
profile
after(:build) do |item|
item.attachments << FactoryGirl.build(:attachment, attachable: item)
end
end
end
I guess doing FactoryGirl.attributes_for isn't actually a build, so the after(:build) won't fire. How about this:
FactoryGirl.attributes_for(:item, :profile_attributes => FactoryGirl.attributes_for(:profile), :attachments => [FactoryGirl.attributes_for(:subject)])
Probably a good idea to try this line in the rails console first to see what the hash comes out like :)
I am getting an undefined method for 'should' in my controller tests and cannot figure out why. I spent some time on google and stack overflow, but am stuck. Any help?
Spec Helper:
require 'simplecov'
SimpleCov.start 'rails'
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.expect_with :rspec do |c|
c.syntax = :expect
end
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
#config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = false
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
end
Capybara.javascript_driver = :webkit
Controller Test:
require 'spec_helper'
include Devise::TestHelpers
describe PagesController do
# This should return the minimal set of attributes required to create a valid
# Page. As you add validations to Page, be sure to
# update the return value of this method accordingly.
def valid_attributes
{ }
end
# This should return the minimal set of values that should be in the session
# in order to pass any filters (e.g. authentication) defined in
# PagesController. Be sure to keep this updated too.
def valid_session
{}
end
describe "GET index" do
it "assigns all pages as #pages" do
page = Page.create! valid_attributes
get :index, {}, valid_session
assigns(:pages).should eq([page])
end
end
describe "GET show" do
it "assigns the requested page as #page" do
page = Page.create! valid_attributes
get :show, {:id => page.to_param}, valid_session
assigns(:page).should eq(page)
end
end
describe "GET new" do
it "assigns a new page as #page" do
get :new, {}, valid_session
assigns(:page).should be_a_new(Page)
end
end
describe "GET edit" do
it "assigns the requested page as #page" do
page = Page.create! valid_attributes
get :edit, {:id => page.to_param}, valid_session
assigns(:page).should eq(page)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Page" do
expect {
post :create, {:page => valid_attributes}, valid_session
}.to change(Page, :count).by(1)
end
it "assigns a newly created page as #page" do
post :create, {:page => valid_attributes}, valid_session
assigns(:page).should be_a(Page)
assigns(:page).should be_persisted
end
it "redirects to the created page" do
post :create, {:page => valid_attributes}, valid_session
response.should redirect_to(Page.last)
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved page as #page" do
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
post :create, {:page => { }}, valid_session
assigns(:page).should be_a_new(Page)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
post :create, {:page => { }}, valid_session
response.should render_template("new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested page" do
page = Page.create! valid_attributes
# Assuming there are no other pages in the database, this
# specifies that the Page created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
Page.any_instance.should_receive(:update_attributes).with({ "these" => "params" })
put :update, {:id => page.to_param, :page => { "these" => "params" }}, valid_session
end
it "assigns the requested page as #page" do
page = Page.create! valid_attributes
put :update, {:id => page.to_param, :page => valid_attributes}, valid_session
assigns(:page).should eq(page)
end
it "redirects to the page" do
page = Page.create! valid_attributes
put :update, {:id => page.to_param, :page => valid_attributes}, valid_session
response.should redirect_to(page)
end
end
describe "with invalid params" do
it "assigns the page as #page" do
page = Page.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
put :update, {:id => page.to_param, :page => { }}, valid_session
assigns(:page).should eq(page)
end
it "re-renders the 'edit' template" do
page = Page.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
put :update, {:id => page.to_param, :page => { }}, valid_session
response.should render_template("edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested page" do
page = Page.create! valid_attributes
expect {
delete :destroy, {:id => page.to_param}, valid_session
}.to change(Page, :count).by(-1)
end
it "redirects to the pages list" do
page = Page.create! valid_attributes
delete :destroy, {:id => page.to_param}, valid_session
response.should redirect_to(pages_url)
end
end
end
Errors:
Failures:
1) PagesController GET index assigns all pages as #pages
Failure/Error: assigns(:pages).should eq([page])
NoMethodError:
undefined method `should' for #<Array:0x007fb986c42948>
# ./spec/controllers/pages_controller_spec.rb:23:in `block (3 levels) in <top (required)>'
2) PagesController POST create with valid params creates a new Page
Failure/Error: expect {
count should have been changed by 1, but was changed by 0
# ./spec/controllers/pages_controller_spec.rb:53:in `block (4 levels) in <top (required)>'
3) PagesController POST create with valid params assigns a newly created page as #page
Failure/Error: assigns(:page).should be_a(Page)
NoMethodError:
undefined method `should' for nil:NilClass
# ./spec/controllers/pages_controller_spec.rb:60:in `block (4 levels) in <top (required)>'
4) PagesController POST create with valid params redirects to the created page
Failure/Error: response.should redirect_to(Page.last)
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb987232c68>
# ./spec/controllers/pages_controller_spec.rb:66:in `block (4 levels) in <top (required)>'
5) PagesController POST create with invalid params assigns a newly created but unsaved page as #page
Failure/Error: assigns(:page).should be_a_new(Page)
NoMethodError:
undefined method `should' for nil:NilClass
# ./spec/controllers/pages_controller_spec.rb:75:in `block (4 levels) in <top (required)>'
6) PagesController POST create with invalid params re-renders the 'new' template
Failure/Error: response.should render_template("new")
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb986e1d1f0>
# ./spec/controllers/pages_controller_spec.rb:82:in `block (4 levels) in <top (required)>'
7) PagesController GET new assigns a new page as #page
Failure/Error: assigns(:page).should be_a_new(Page)
NoMethodError:
undefined method `should' for #<Page:0x007fb982404708>
# ./spec/controllers/pages_controller_spec.rb:38:in `block (3 levels) in <top (required)>'
8) PagesController PUT update with valid params updates the requested page
Failure/Error: put :update, {:id => page.to_param, :page => { "these" => "params" }}, valid_session
#<Page:0x007fb9872517f8> received :update_attributes with unexpected arguments
expected: ({"these"=>"params"})
got: ({})
# ./app/controllers/pages_controller.rb:61:in `block in update'
# ./app/controllers/pages_controller.rb:60:in `update'
# ./spec/controllers/pages_controller_spec.rb:96:in `block (4 levels) in <top (required)>'
9) PagesController PUT update with valid params assigns the requested page as #page
Failure/Error: assigns(:page).should eq(page)
NoMethodError:
undefined method `should' for #<Page:0x007fb981579a30>
# ./spec/controllers/pages_controller_spec.rb:102:in `block (4 levels) in <top (required)>'
10) PagesController PUT update with valid params redirects to the page
Failure/Error: response.should redirect_to(page)
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb9827b7350>
# ./spec/controllers/pages_controller_spec.rb:108:in `block (4 levels) in <top (required)>'
11) PagesController PUT update with invalid params assigns the page as #page
Failure/Error: assigns(:page).should eq(page)
NoMethodError:
undefined method `should' for #<Page:0x007fb987444a88>
# ./spec/controllers/pages_controller_spec.rb:118:in `block (4 levels) in <top (required)>'
12) PagesController PUT update with invalid params re-renders the 'edit' template
Failure/Error: response.should render_template("edit")
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb982e75750>
# ./spec/controllers/pages_controller_spec.rb:126:in `block (4 levels) in <top (required)>'
13) PagesController GET show assigns the requested page as #page
Failure/Error: assigns(:page).should eq(page)
NoMethodError:
undefined method `should' for #<Page:0x007fb9830f3a68>
# ./spec/controllers/pages_controller_spec.rb:31:in `block (3 levels) in <top (required)>'
14) PagesController DELETE destroy redirects to the pages list
Failure/Error: response.should redirect_to(pages_url)
NoMethodError:
undefined method `should' for #<ActionController::TestResponse:0x007fb988100e98>
# ./spec/controllers/pages_controller_spec.rb:142:in `block (3 levels) in <top (required)>'
15) PagesController GET edit assigns the requested page as #page
Failure/Error: assigns(:page).should eq(page)
NoMethodError:
undefined method `should' for #<Page:0x007fb9872585f8>
# ./spec/controllers/pages_controller_spec.rb:46:in `block (3 levels) in <top (required)>'
RSpec offers two ways of writing expectations:
should style 1.should == 1
expect style expect(1).to eq(1)
Your spec_helper is configured to use the latter. Change the syntax config to: c.syntax = :should
Reference: https://www.relishapp.com/rspec/rspec-expectations/docs/syntax-configuration
I've got the following Rspec tests that test whether a user can successfully update a scavenger hunt. I know the site will let the user do this, but my problem is that my tests aren't capturing that. Each time I run rspec, all the tests below fail. I'm hoping there's just one simple thing that I'm forgetting to put in there, but my eyes are bleary all the code's running together. When you look at these tests, does anything strike you as obviously wrong?
describe "PUT 'update'"
before(:each) do
#hunt = FactoryGirl.create(:hunt)
end
....
describe "as an admin user" do
before(:each) do
admin = FactoryGirl.create(:user, :email => "admin#example.com", :admin => true)
test_sign_in(admin)
end
....
describe "success" do
before(:each) do
#attr = { :name => "New Hunt" }
end
it "returns http success" do
get 'edit', :id => #hunt
response.should be_success
end
it "should change the hunt's name" do
put :update, :id => #hunt, :name => #attr
#hunt.reload
#hunt.name.should == #attr[:name]
end
it "should redirect to the hunt show page" do
put :update, :id => #hunt
response.should redirect_to(#hunt)
end
it "should have a flash message" do
put :update, :id => #hunt, :user => #attr
flash[:success].should =~ /updated/
end
end
...
end
Here's code from my controller.
def edit
#hunt = Hunt.find(params[:id])
#title = "Edit hunt"
end
def update
#hunt = Hunt.find(params[:id])
if #hunt.update_attributes(params[:hunt])
flash[:success] = "Hunt updated."
redirect_to hunts_path
else
#title = "Edit Hunt"
render 'edit'
end
end
And here's the feedback I'm getting form Rspec. It's all across the boards, but I'm hoping it's caused by a single problem and not four individual ones.
1) HuntsController PUT 'update' as an admin user failure should render the 'edit' page
Failure/Error: response.should render_template('edit')
expecting <"edit"> but rendering with <"">
# ./spec/controllers/hunts_controller_spec.rb:220:in `block (5 levels) in <top (required)>'
2) HuntsController PUT 'update' as an admin user failure should have the right title
Failure/Error: response.should have_selector("title", :content => "Edit hunt")
expected following output to contain a <title>Edit hunt</title> tag:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>You are being redirected.</body></html>
# ./spec/controllers/hunts_controller_spec.rb:226:in `block (5 levels) in <top (required)>'
3) HuntsController PUT 'update' as an admin user success should change the hunt's name
Failure/Error: #hunt.name.should == #attr[:name]
expected: "New Hunt"
got: "Hunt 9" (using ==)
# ./spec/controllers/hunts_controller_spec.rb:244:in `block (5 levels) in <top (required)>'
4) HuntsController PUT 'update' as an admin user success should redirect to the hunt show page
Failure/Error: response.should redirect_to(#hunt)
Expected response to be a redirect to <http://test.host/hunts/649> but was a redirect to <http://test.host/hunts>
# ./spec/controllers/hunts_controller_spec.rb:249:in `block (5 levels) in <top (required)>'