Rspec not changing count on create
Whenever our tests give us unexpected trouble, it's important to take a step back and re-evaluate our approach. Usually, this is an indication of some design problem, either with the code we're testing or with tests themselves.
While it sounds like using a truncation strategy has fixed this particular problem (see more on that below), i would suggest that there is more to learn from the situation.
Consider the two examples from your spec above. The only difference between them comes down to whether the code
parameter is valid or not. I would argue that these examples are really testing the Group
model, not the controller.
Now, if we're confident in our model test coverage, then we can take a different approach to the controller spec. From the controller's perspective, the model is a collaborator and in general, we always want to avoid indirectly testing collaborators. In this case, we can use a mock to simulate the behavior of the Group
model and only test the controller behavior in isolation.
Something like this (please note the code below is incomplete and untested):
# spec/controllers/groups_controller_spec.rb
describe "#create" do
before do
# use a Test Double instead of a real model
@new_group = double(Group)
@params = { :cdb_group => 'stub_cdb_group_param', :service_id => service }
# using should_receive ensures the controller calls new correctly
Group.should_receive(:new).with(@params[:cdb_group]).and_return(@new_group)
end
context "when cancelled responding to js" do
it "renders hide_new" do
post :create, @params.merge({:button => "cancel", :format => "js"})
expect(response).to render_template('hide_new')
end
end
context "with valid params" do
before do
@new_group.should_receive(:save).and_return(true)
end
context "responding to json" # ...
context "responding to html" # ...
context "responding to xml" #...
end
context "with invalid params" do
before do
@new_group.should_receive(:save).and_return(false)
end
# ...
end
end
While the above doesn't specifically address the problem with record counts you were having, i suspect the problem may go away once you isolate your test targets correctly.
If you choose to stick with database truncation, consider using it selectively as described here.
I hope at least some of that helps :).
Rails 5 - Rspec Expect Change Count Not Working
Ok, so I figured out why it wasn't saving a new Post record. For whatever reason, the author that was supposed to be assigned to the post in the :post factory was not being created. This meant that a validation failed.
This is the :post factory I was using:
FactoryGirl.define do
factory :post do
title { Faker::Lorem.sentence }
excerpt { Faker::Lorem.paragraph }
content { Faker::Lorem.paragraph }
published false
published_at nil
post_type "article"
keywords "blog, post, key, words"
author
end
end
And this was my :author factory for my Devise Author model:
FactoryGirl.define do
factory :author do
email { Faker::Internet.email }
password "password"
password_confirmation "password"
end
end
When I was generating the attributes using the FactoryGirl
attributes_for(:post)
method, the author was not being created and therefore the author_id attribute of the post was not being set.
To fix this I had to create the author in the test then set the author_id attribute in the attributes_for
method.
So my working test now looks like this:
it "saves the new Post in the database" do
author = create(:author)
expect{
process :create, method: :post, params: { post: attributes_for(:post, author_id: author.id) }
}.to change{Post.count}.by(1)
end
Although this solves my original problem, I'm not sure why the Author was not being created and associated to the Post within the attributes_for
call.
How to create two user records and then verify user count is 2 in rspec?
You have attr_accessor :admin
which overrides the setters and getters for the admin
column. You also need to make sure that the factory contains the minimum requirement in order for you to create a record. This means that you have to use sequencing for username
and add password
and password_confirmation
to your factory.
The final thing you need to do is to remove the attr_accessor :admin
line and your tests should pass.
RSpec ActiveRecord::RecordNotFound
In your request, you're doing post :create, { appointment: { dentist_id: '1', ... } }
, which means that params[:dentist_id]
in your controller will be nil
(notice how you're nesting dentist_id
under appointment
in your request params). To fix this, change @dentist = Dentist.find(params[:dentist_id])
in your controller action to @dentist = Dentist.find(params[:appointment][:dentist_id])
, or change your request to post :create, { dentist_id: '1', appointment: { patient_id: '2' ... } }
.
Update
You'll also need to create a Dentist
record in your database before the test is run. To do that, add something like this to your test case:
describe 'POST #create' do
before { Dentist.create!(id: 1) }
it 'assigns a newly created appointment as @appointment' do
post :create, { dentist_id: '1', appointment: { patient_id: '2', appt_date: '2015-12-05 09:00:00' } }
...
end
end
Create method test keeps failing with RSpec
What is happening is when you send a request using invalid_attributes
, your controller still takes the successful path through your code. You can tell from your two failures. Rendering with <[]>
happens on a redirect, and object instances only have an id
and created_at
if they've been saved.
This would indicate that you're not validating presence of name
in your Survey
model:
# app/models/survey.rb
class Survey < ActiveRecord::Base
belongs_to :user
validates :name, presence: true
end
and thus it is saved successfully with a blank name.
rspec controller builds multiple records in one form
OK, I worked this out. So in the controller spec for a model that builds two models in a form.
the controller spec could should be
post :create, :account => attributes_for(:account).merge(users_attributes: [ attributes_for(:user) ])
response.should redirect_to "http://test.host/subscribe/subcode/1/user-2"
Sorry for the earlier poor description of where the error was, but hope this helps anyone else with the same issue
Rails 5 rspec - convert object to ActiveRecord Relation
The simple way to do it is to use create_list
and return an ActiveRecord
relation, but if I were you I'd rethink it to use stubs
.
let(:array) do
list = create_list(:class_example, 4)
ClassExample.where(id: list.map(&:id))
end
Why do I receive this RSpec error when I try to create a factory?
Try adding the following line to your spec_helper.rb
file:
require 'factory_girl'
Also, add these lines to your spec_helper.rb
:
FactoryGirl.definition_file_paths.clear
FactoryGirl.definition_file_paths << File.expand_path('../factories', __FILE__)
FactoryGirl.find_definitions
and remove them from RSpec.configure do |config|
block.
Also, make sure you defined your factories in the correct file. It should be defined in factories.rb
in your test folder (spec) if you use rspec.
Update
FactoryGirl.definition_file_paths.clear
FactoryGirl.definition_file_paths << "./spec/factories"
FactoryGirl.find_definitions
These lines should go to your spec/support/factory_girl.rb
file and remove them from anywhere else.
Also, add the following in your spec_helper.rb
:
config.before(:all) do
FactoryGirl.reload
end
In your spec_helper.rb
the Rspec.configure
block should look like this:
RSpec.configure do |config|
config.mock_with :rspec
config.run_all_when_everything_filtered = true
config.filter_run :focus
config.include FactoryGirl::Syntax::Methods
end
Update
Add this to your rails_helper.rb
:
require_relative 'support/factory_girl.rb'
And then it should work.
Related Topics
How to Strip Commas from Float Input
Rspec - How to Test Activerecord::Recordnotfound
If Referer = "/Search", Do X, Else Do Y: "Bad Argument (Expected Uri Object or Uri String)"
Does Will Pagination Work with Forms Which Have Method="Post"
Pow Not Loading Gem Properly While Rails S Works
How to Add "Access-Control-Allow-Origin" Headers to API Response in Ruby
Mongomapper Many to Many Issue with Array
Ruby Was-Sdk V2:Seahorse::Client::Networkingerror Exception: Ssl_Connect
Create and Initialize Instances of a Class with Sequential Names
Accessing Values Through Ajax Calls and Partials in Rails
Metasploit Induction of Bundle and Rake
Deleting a Line in a Text File
Ruby Selenium Web Drive: How to Find Specific Element by Xpath Div Id and CSS Class
How to Convert a Formatted String into Plain Text
Perfect Way to Write a Gsub for a Regex Match
Why Must I Explicitly Call Self on Accessor When Using the Array Union Operator |= in Ruby
How to Use 'Debugger' and 'Pry' When Developing a Gem? (Ruby)