Why isn't factory_girl operating transactionally for me? - rows remain in database after tests
Finally fixed this and I hope I can save someone the six hours of debugging it took me to figure it out.
By a) getting lucky and ending up with a version of code that worked and b) stripping both sets of code down this is what I found:
Test that chokes up
require 'spec_helper'
describe UsersController do
@user = Factory.create(:user)
end
Test that works
require 'spec_helper'
describe UsersController do
it "should make a factory models without choking" do
@user = Factory.create(:user)
end
end
The transaction is defined by the it "should do something" do... statement. If you instantiate the factory outside that statement it turns out not to be transactional.
You can also put it outside the "it should.." block as long as it's in a "before..end" block
require 'spec_helper'
describe UsersController do
before(:each) do
@user = Factory.create(:user)
end
it 'should make a factory without choking' do
puts @user.name
# prints out the correnct name for the user
end
end
On experimenting, it seems to be valid to define a user outside of an "it should do..end" block as long as it's in a "before.. end" block. I guess this is only executed in the scope of the "it should do..end" block and therefore works fine.
[Thanks to @jdl for his (also correct) suggestion]
factory_girl causing RSpec spec to fail after Rails 4 upgrade
The question marks aren't a problem; they're placeholders for the values.
This part of your array of values
["career_goal", ["Illum et sunt.", "Illo sapiente nesciunt reiciendis nulla fugit est autem."]]
indicates that career_goal
is set to an array. Change it to a single string (with join
or by rewriting it, whatever).
FactoryGirl, Rspec, let, and before issues
Check the rspec doc: https://www.relishapp.com/rspec/rspec-core/v/2-11/docs/helper-methods/let-and-let
Note that let is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked. You can use let! to force the method's invocation before each example.
In other words if you use let
along with factory_girl
a record will not be created before let-variable invocation.
The correct code is:
# will test that get_count_for_list will return 5
describe ApiController do
# why same name - seems really confusing!
let!(:user) { FactoryGirl.create(:user) }
let!(:user2) { FactoryGirl.create(:user2) }
Is it possible to use FactoryGirl without Rails?
By default factory_girl creates saved instances. If you don't want to save the object to the database, you can create unsaved instances using the build
method.
require 'spec_helper'
require 'note'
describe Note do
it "should return body" do
@note = Factory.build(:note)
note.body.should == 'body of a note'
end
end
See "Using Factories" in the Getting Started file.
Database not being cleared when using Capybara and RSPEC
For anyone who needs this in the future, this problem has been solved.
Like zetetic said, I can't use Capybara with transactional fixtures.
To fix the problem, I used Database Cleaner.
gem install database_cleaner
Gemfile:
group :test do
gem 'database_cleaner'
end
bundle install
spec/spec_helper.rb:
config.use_transactional_fixtures = false
...
module ::RSpec::Code
class ExampleGroup
include Capybara::DSL
include Capybara::RSpecMatchers
end
end
foo_bar file:
before(:all) {
...
DatabaseCleaner.strategy = :truncation
}
after(:all) {
...
DatabaseCleaner.clean
Capybara.reset_sessions!
Capybara.use_default_driver
}
Skip callbacks on Factory Girl and Rspec
I'm not sure if it is the best solution, but I have successfully achieved this using:
FactoryGirl.define do
factory :user do
first_name "Luiz"
last_name "Branco"
#...
after(:build) { |user| user.class.skip_callback(:create, :after, :run_something) }
factory :user_with_run_something do
after(:create) { |user| user.send(:run_something) }
end
end
end
Running without callback:
FactoryGirl.create(:user)
Running with callback:
FactoryGirl.create(:user_with_run_something)
Invalid record when declaring two Factories in before (:each) in Rspec
The knowledge class has an associated professor record. Since you are not pasing an explicit professor record to the create method, you are creating a new professor at the same time you creates the knowledge.
One way or another, you are creating two professors with the same attributes. There must be a validation of uniqueness or something like this.
Try this:
before (:each) do
@professor = FactoryGirl.create(:professor)
@knowledge = FactoryGirl.create(:knowledge, :professor => @professor)
sign_in @professor
end
It should work.
Related Topics
How to Use Factorygirl to Create an Attribute Called "Alias"
What the Purpose of Bind/Unbind Methods in Ruby
Generating Sequential Numbers in Multi-User Saas Application
What's the Best Way to Start a Background Process, That Can Get Accessed Later On
Download and Write .Tar.Gz Files Without Corruption
Working with a Large Data Object Between Ruby Processes
Why Is Ruby Throwing a Segmentation Fault on Only My System, and Only in This Rails Application
Get Table Name from Activerecord
Alter Rails Params Hash from Rack Middleware
Ruby: Multiply All Elements of an Array
Terminal Not Executing Ruby Files
How to Remove All Characters in a String Until a Substring Is Matched, in Ruby
Ruby on Rails - Rack-Cors Multiple Origins with Different Resources
Postgresql Ilike with Multiple Matches in Rails Activerecord
Application.CSS Not Being Served as an Asset
Normal Variables VS Instance Variable in Ruby, Whats the Difference