FactoryGirl and Rails 3.2 error - ruby

I have this in factories.rb:
FactoryGirl.create :user do |user|
user.name "test"
user.age "40"
end
and this in my test file:
require 'spec_helper'
describe "FirstTests" do
it "creates a user" do
user=Factory(:user)
end
end
Like always nothing works. Could somebody explain me why I am getting this?
/usr/local/rvm/gems/ruby-1.9.3-p194/gems/factory_girl-4.1.0/lib/factory_girl/registry.rb:24:in `find': Factory not registered: user (ArgumentError)
Everything is there. why I am getting this error?

You are using create instead of define
FactoryGirl.define do
factory :user do
name "test"
age "40"
end
end
and Factory(:user) instead of FactoryGirl.create(:user), or more simply create(:user)
https://github.com/thoughtbot/factory_girl/wiki/Usage

Related

FactoryGirl not passing arguments in build

I have a ruby app that I'm using rspec and factorygirl with, and I'm having trouble building a factory. When I run the spec, I get an ArgumentError: missing keywords for the required keywords in initialize. If I pass them in explicitly, the error changes to wrong number of arguments 0 for 2.
Thanks for any help on this.
spec/models/player_spec.rb
require 'spec_helper'
describe Player do
it 'has a valid factory' do
player = build(:player) # or build(:player, name: 'testname', password: 'testpw')
end
end
spec/factories/player.rb
FactoryGirl.define do
factory :player do
name { 'Testname' }
password { 'testpass' }
end
end
models/player.rb
def initialize(name:, password:)
#id = object_id
#name = name
#password = password
end
Change your spec/factories/player.rb with:
FactoryGirl.define do
factory :player do
name 'Testname'
password 'testpass'
initialize_with { new(name:name, password: password) }
end
end
You can find the documentation here although is not explicit to be used in this case.
Did you try to use the syntax that they recommend on the github repo Read Me?
It looks like defining a factory is done with the following syntax:
FactoryGirl.define do
factory :player do
name 'Testname'
password 'testpass'
end
end
They may be equivalent, but this stood out to me as being a potential problem. It seems that blocks are used whenever you are executing logic, not declaring.
I finally got this to work by changing the player#initialize method to accept an options hash instead of keyword arguments params.

Rspec + Factory girl (without rails!)

I am using Rspec with selenium-webdriver gem to test a web app. And I wanted to unclude factories in my tests to emulate users and not to create a user manually each time.
So, I made gem install factory_girl, added required lined in my spec_helper, created a factory and included some lines in my spec file. And when running the test I get an error
Failure/Error: FactoryGirl.build(:user)
NameError:
uninitialized constant User
Here is my spec_helper.rb
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
My factories.rb file:
FactoryGirl.define do
factory :user do
name "testuser"
password "freestyle"
inventory true
end
end
And my test_spec file:
require "json"
require "selenium-webdriver"
require "rspec"
require "factory_girl"
FactoryGirl.find_definitions
include RSpec::Expectations
describe "MallSpec" do
before(:all) do
FactoryGirl.build(:user)
#driver = Selenium::WebDriver.for :firefox
#base_url = "http://localhost:9000/"
#accept_next_alert = true
#driver.manage.timeouts.implicit_wait = 30
#driver.manage.window.resize_to(1301, 744)
#verification_errors = []
end
My spec_file is in the root dir of the project. my factories.rb file is in /spec dir as well as the test_spec.rb itself.
Can anyone help me with this issue or point what i am doing wrong?
If you don't actually have a User class but you want to use FactoryGirl to generate the attributes, you can override the class:
require "ostruct"
FactoryGirl.define do
factory :user, class: OpenStruct do
name "testuser"
password "freestyle"
inventory true
# This isn't necessary, but it will prevent FactoryGirl from trying
# to call #save on the built instance.
to_create {}
end
end
You can then use attributes_for if you just want a Hash, or create if you want an object that responds to methods like name.
You can use a library like Hashie::Mash if you want to generate JSON for use in your API:
factory :user, class: Hashie::Mash do
# ...
end
# In your tests:
user_json = create(:user).to_json
And when running the test I get an error Failure/Error:
FactoryGirl.build(:user) NameError: uninitialized constant User
Your User class has to be defined. The following is a test with no User class defined:
require 'factory_girl'
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
FactoryGirl.define do
factory :user do
name 'Alice'
age 10
end
end
describe "MallSpec" do
let(:test_user) { FactoryGirl.build(:user) }
describe "user's name" do
it "equals 'Alice'" do
expect(test_user.name).to eq('Alice')
end
end
end
--output:--
$ rspec 1.rb
F
Failures:
1) MallSpec user's name equals 'Alice'
Failure/Error: let(:user) { FactoryGirl.build(:user) }
NameError:
uninitialized constant User
...
Adding a definition for the User class:
require 'factory_girl'
#====NEW CODE=====
class User
attr_accessor :name, :age
end
#=================
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
FactoryGirl.define do
factory :user do
name 'Alice'
age 10
end
end
describe "MallSpec" do
let(:test_user) { FactoryGirl.build(:user) }
describe "user's name" do
it "equals 'Alice'" do
expect(test_user.name).to eq('Alice')
end
end
end
--output:--
$ rspec 1.rb
.
Finished in 0.0024 seconds (files took 0.35197 seconds to load)
1 example, 0 failures
I expect that the factory() method here:
factory :user do
name 'Alice'
age 10
end
...does something like this:
def factory(model_name)
target_class = constant_get(model_name.capitalize)
...in order to construct a real instance of the User class. In other words, factory_girl constructs instances of classes that already exist in your app--factory_girl does not mock a class.

FactoryGirl doesn't write data

I am so confused as to why this is happening...
I'm using factory girl, and this factory:
# spec/factories/partners/contact.rb
FactoryGirl.define do
factory :partner_contact, class: Partners::Contact do
first_name "Josh"
last_name { Faker::Name.last_name }
email { Faker::Internet.email }
partner
end
end
But when I run my rspec it says
Mysql2::Error: Field 'first_name' doesn't have a default value: INSERT INTO `partner_contact` (`created_on`) VALUES ('2014-01-30 22:21:53')
Here is the spec that I'm using that generates the above error.
# spec/models/contact.rb
require 'spec_helper'
require 'pp'
describe Partners::Contact do
it "has a valid factory" do
partner = FactoryGirl.create(:partner_contact)
# partner.should be_valid
puts "MEOW MEOW"
end
it "is invalid without a firstname" do
# FactoryGirl.build(:partner_contact, first_name: nil).should_not be_valid
end
it "is invalid without a lastname" do
# FactoryGirl.build(:partner_contact, last_name: nil).should_not be_valid
end
it "is invalid without an email address" do
# FactoryGirl.build(:partner_contact, email: nil).should_not be_valid
end
#it "returns a contact's fullname as a string"
end
As you can see, it's not trying to commit any data that I listed, first_name, last_name or email. Just 'created_on' which is generated via rails.
What's going on here?
Do you have any fixtures for that table? If fixtures are present and enabled, Rails will attempt to load them into your database before your test is evaluated. Look in spec/fixtures.
Your setup seems wrong. Check the FactoryGirl Rails gem. Don't forget to configure RSpec to use FactoryGirl as well.

NoMethodError with 'sign_in' using Devise::TestHelpers

I'm trying to get Devise's helper methods to work for a controller spec. Here's the relevant code:
# spec/spec_helper.rb
RSpec.configure do |config|
# other config stuff ...
config.include Devise::TestHelpers, :type => :controller
end
#spec/controllers/posts_controller_spec.rb
require 'spec_helper'
describe PostsController do
describe "GET index" do
admin = FactoryGirl.create(:admin)
sign_in admin # NoMethodError occurs
it "does something..." do
# etc etc etc
end
You have to be authenticated to render the template from this route, which is why I'm trying to sign in an admin so the test will pass. Thanks for your help.
I think that the sign_in method must be used in a context of it or before blocks. Try:
before do
admin = FactoryGirl.create(:admin)
sign_in admin # NoMethodError occurs
end

Rails 3.1 Rspec Creating test case validate field for Model

I'm trying to create a test case for User model. Basically, it will validate first_name and last_name to be present.
What I am trying to do is to check whether the error on a specific field is empty or not and it should be empty. However it always fails.
What is the correct way to do this?
Here is my code
On my user_spec.rb
require 'spec_helper'
describe User do
before do
#user = User.new
end
it "must have a first name" do
#user.errors[:first_name].should_not be_empty
end
it "must have a last name" do
#user.errors[:last_name].should_not be_empty
end
end
On my user.rb file
class User < ActiveRecord::Base
validates :first_name, :presence => true
validates :last_name, :presence => true
end
You can test by simply doing this as well:
describe 'validations' do
it { should validate_presence_of :firstname }
it { should validate_presence_of :lastname }
end
Take a look at the shoulda matchers for all such standard Rails Validation.
This way is not just more concise but also takes care of the positive case. Meaning you then dont need to test the scenario mentioned below:
it "passed validations when first_name is set"
user = User.create(:firstname => 'f', :lastname => 'l')
user.errors[:first_name].should be_empty
user.errors[:last_name].should be_empty
end
RSpec supports the notion of an "implicit" subject. If your first argument to the "describe" block is a class, RSpec automatically makes an instance of that class available to your specs. See http://relishapp.com/rspec/rspec-core/v/2-6/dir/subject/implicit-subject.
require 'spec_helper'
describe User do
it "must have a first name" do
subject.should have(1).error_on(:first_name)
end
it "must have a last name" do
subject.should have(1).error_on(:last_name)
end
end
which results in RSpec output (if using --format documentation) of:
User
must have a first name
must have a last name
You can abbreviate it even further if you are content with the RSpec output defaults:
require 'spec_helper'
describe User do
it { should have(1).error_on(:first_name) }
it { should have(1).error_on(:last_name) }
end
which results in:
User
should have 1 error on :first_name
should have 1 error on :last_name

Resources