Rails 3: uninitialized constant FactoryGirl - ruby-on-rails

I am trying to create my first controller test using FactoryGirl for my Rails application, but I keep retrieving the following error:
uninitialized constant FactoryGirl
My Factories.rb file looks like this:
FactoryGirl.define do
factory :offer, class: "Offer" do |f|
f.title "Some title"
f.description "SomeDescription"
end
end
And my controller test looks like this:
require 'spec_helper'
describe OffersController do
def valid_session
{}
end
describe "GET index" do
before {
#offer = FactoryGirl.create(:offer)
}
it "assigns all offers as #offers" do
get :index, {}, valid_session
assigns(:offers).should eq([#offer])
end
end
end
My Gemfile looks like this:
group :development, :test do
gem 'sqlite3'
gem 'rspec-rails'
gem 'capybara', '1.1.2'
gem 'factory_girl_rails', '>= 4.1.0', :require => false
end
What might I be missing since FactoryGirl isn't present?

You propably forgotten to require factory_girl in spec_helper.rb.

Related

Factory not defined for RSPEC test Ruby

I 'm trying to write an RSpec test for this service. The service below essentially just makes a call to some endpoint and then create data in the postgres DB.
class SomeService
API_URL = "someEndPoint"
def process
get_reviews
end
def get_reviews
conn = Faraday.new(url: "#{APIURL}/#{ENV["ID"]}/reviews?language=en&stars=5") do |faraday|
faraday.headers["apikey"] = ENV["KEY"]
faraday.adapter Faraday.default_adapter
end
response = conn.get
imported_reviews = []
results = JSON.parse(response.body)
results["reviews"].each do |item|
review = SomeModel.create(
title: item["title"],
body: item["text"],
posted_at: item["createdAt"],
link: "https://somelink.com/#{item["id"]}",
display_name: item["consumer"]["displayName"]
)
imported_reviews << review
end
imported_reviews
end
end
My model is just the boilerplate model shown as:
class SomeModel < ApplicationRecord
end
This is my spec file some_service_spec.rb. I've written plenty of tests in JEST but it's just so foreign to me in Ruby.
# frozen_string_literal: true
require 'rails_helper'
describe TrustpilotService do
describe "#process" do
context 'with valid API_KEY' do
before :all do
WebMock.allow_net_connect!
end
after :all do
WebMock.disable_net_connect!(allow_localhost: true)
end
it "should import reviews to database" do
key = "90e0dbc7160d4024a1f12bc24b3d1def" #fake key#
some_review = create(title: 'Blah', body: 'Blah blah', posted_at: '2019-09-30T20:35:14Z', link: 'https://somelink.com/reviews/asdf123', display_name: 'Jane Doe')
some_review.save!
service = described_class.new
expect{ service.process }.to change{ SomeModel.count }
end
end
end
end
Edit added my factory for reference
FactoryBot.define do
factory :trustpilot_review do
end
end
Gem File
group :test do
gem "capybara", "~> 3.29.0"
gem 'database_cleaner'
gem 'factory_bot_rails'
gem 'rails-controller-testing'
gem 'rspec-rails', '~> 3.8'
gem 'rspec-snapshot', '~> 0.1.2'
gem "shoulda-matchers"
gem "simplecov", require: false
gem 'timecop'
gem "webdrivers"
gem 'webmock'
end
I essentially was just trying to replicate another spec file that was testing a service that does sort of the same thing but I'm getting Factory not registered: as an error. I created a factory but not entirely sure what to even put in it. All of the info on RSPEC out there is kind of outdated. As you can tell, I'm pretty new to Ruby so any help is appreciated.
If this is the way you are calling your factory, then you missed naming the factory:
some_review = create(title: 'Blah', body: 'Blah blah', posted_at: '2019-09-30T20:35:14Z', link: 'https://somelink.com/reviews/asdf123', display_name: 'Jane Doe')
Try
some_review = create(:trustpilot_review, title: 'Blah', body: 'Blah blah', posted_at: '2019-09-30T20:35:14Z', link: 'https://somelink.com/reviews/asdf123', display_name: 'Jane Doe')
Also it seems to me that the title, link, etc, should mostly be in the factory definition which is the point of factories.
If you want to use factory name with different name of model name. then need to add class_name like below:
FactoryBot.define do
factory :trustpilot_review, class: 'SomeModel' do
end
end

Tell rspec (core) that test is testing controller

Trying to run this test but keep getting the following error:
Failure/Error: get :index
NoMethodError:
undefined method `get' for #<RSpec::ExampleGroups::TestModuleTestController::Controller:0x007fa4bc120d00>
Note: I'm not using rspec-rails.
require "spec_helper"
module TestModule
describe TestController, :type => :controller do
describe "controller" do
it "sets X-Frame-Options to ALLOWALL" do
get :index
expect(response.headers['X-Frame-Options']).to eq('ALLOWALL')
end
end
end
end
Note: I'm not using rspec-rails.
That's your problem right there. All the rails type specs (controller, request, features, views) are part of rspec-rails not rspec-core.
Without rspec-rails the type metadata does absolutely nothing - its just a plain example group describing a class.
The solution is to add rspec-rails to your gemfile.
group :development, :test do
gem 'rspec-rails', '~> 3.6'
end
And run rails g rspec install.
https://github.com/rspec/rspec-rails

How to pass Rspec test has_many? [Shoulda-matchers]

I´m trying rails to develop a rest api. I´m using rspec and shoulda-matchers. The problem is that one of my test always fails.
How can I correct my code, so the test passes (GREEN).
user.rb
class User < ActiveRecord::Base
has_many :cards
end
card.rb
class Card < ActiveRecord::Base
belongs_to :user
end
user_spec.rb
require 'rails_helper'
RSpec.describe User, type: :model do
before { #user = FactoryGirl.create(:user) }
subject{ #user }
# Columns
it { should respond_to :name }
# Associations
it { should have_many :cards }
end
Gemfile
source 'https://rubygems.org'
gem 'rails', '4.2.0'
gem 'rails-api'
gem 'spring', :group => :development
gem 'sqlite3'
group :development, :test do
gem 'factory_girl_rails'
gem 'rspec-rails', '~> 3.0'
gem 'shoulda-matchers', '~> 3.0'
end
Terminal
➜ my_api rspec spec/models/user_spec.rb
.F
Failures:
1) User should have many :cards
Failure/Error: it { should have_many :cards }
expected #<User:0x007f897ce0c0d8> to respond to `has_many?`
# ./spec/models/user_spec.rb:12:in `block (2 levels) in <top (required)>'
Finished in 0.04623 seconds (files took 2.45 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/models/user_spec.rb:12 # User should have many :cards
You have to setup the association between the models properly in your user and card factories.
factory :card do
# ...
association :user
end
Then, it should work.
See this to know more about associations in factory-girl.
If the above doesn't fix your problem, try doing this way:
# spec/factories/user.rb
Factory.define :user, :class => User do |u|
u.cards { |c| [c.association(:card)] }
end

rails rspec tests for lib class used by routes contains private methods

Simplecov detected that I was missing some tests on my lib/api_verson.rb class:
class ApiVersion
def initialize(version)
#version = version
end
def matches?(request)
versioned_accept_header?(request) || version_one?(request)
end
private
def versioned_accept_header?(request)
accept = request.headers['Accept']
accept && accept[/application\/vnd\.#{Rails.application.secrets.my_app_accept_header}-v#{#version}\+json/]
end
def unversioned_accept_header?(request)
accept = request.headers['Accept']
accept.blank? || accept[/application\/vnd\.#{Rails.application.secrets.my_app_accept_header}/].nil?
end
def version_one?(request)
#version == Rails.application.secrets.my_app_default_api_version && unversioned_accept_header?(request)
end
end
This class is used by the routes file to help setup api versions:
namespace :api, path: "", defaults: {format: :json} do
scope module: :v1, constraints: ApiVersion.new(1) do
get '/alive', to: 'api#alive'
end
scope module: :v2, constraints: ApiVersion.new(2) do
get '/alive', to: 'api#alive'
end
end
This setup was ported from versioning_your_ap_is.
I am trying to test the methods here that simplecov is reporting as failures:
require 'spec_helper'
describe ApiVersion do
before(:each) do
#apiversion = ApiVersion.new(1)
#request = ActionController::TestRequest.new(host: 'localhost')
#request.headers["Accept"] = "application/vnd.#{Rails.application.secrets.my_app_accept_header}-#{Rails.application.secrets.my_app_default_api_version}+json"
end
describe 'Method #versioned_accept_header =>' do
it 'Should return the correct accept header version' do
binding.pry
end
end
end
I am trying to build this first test to attempt??? to #apiversion.send(:unversioned_accept_header, #request) and I am getting the error:
#apiversion.send(:unversioned_accept_header, #request)
NoMethodError: undefined method `unversioned_accept_header' for #<ApiVersion:0x007fae009bdad8 #version=1>
from (pry):1:in `block (3 levels) in <top (required)>'
Basically the following methods are flagged: "matches?, versioned_accept_header?, unversioned_accept_header?, and version_one?"
I am not the rockstar at rspec and could use some pointers here. Thank you for your help.
Btw, this is a rails 4 application running:
group :development, :test do
gem 'pry'
gem 'pry-doc'
gem 'pry-debugger'
gem 'pry-rails'
gem 'pry-plus'
gem 'pry-rescue'
gem 'pry-stack_explorer'
gem 'pry-clipboard'
gem 'pry-nav'
gem 'rspec-rails'
gem 'factory_girl_rails'
gem 'faker'
gem 'seedbank'
gem 'capybara'
end
group :test do
gem 'simplecov', '~> 0.7.1'
gem 'shoulda-matchers'
gem 'spork-rails'
gem 'database_cleaner'
gem 'email_spec'
gem 'timecop'
gem 'json_spec'
end
You run this code
#apiversion.send(:unversioned_accept_header, #request)
but you have method:
def unversioned_accept_header?(request)
accept = request.headers['Accept']
accept.blank? || accept[/application\/vnd\.#{Rails.application.secrets.my_app_accept_header}/].nil?
end
try change
#apiversion.send(:unversioned_accept_header, #request) -> #apiversion.send(:unversioned_accept_header?, #request)
or change method name
def unversioned_accept_header? -> def unversioned_accept_header

railstutorial.org - undefined method `Factory'

I'm attempting to follow railstutorial.org, and am currently on Chapter 7, where you start using factories: http://railstutorial.org/chapters/modeling-and-viewing-users-two#sec:tests_with_factories
I'm using Rails 3.0.1 and ruby-1.9.2-p0
I can't for the life of me get my rspec tests to pass though, the error i get is
Failures:
1) UsersController GET 'show' should be successful
Failure/Error: #user = Factory(:user)
undefined method `Factory' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_1:0x00000101cc5608>
# ./spec/controllers/users_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
my factories.rb looks like this:
# By using the symbol ':user', we get Factory Girl to simulate the User model.
Factory.define :user do |user|
user.name "Michael Hartl"
user.email "mhartl#example.com"
user.password "foobar"
user.password_confirmation "foobar"
end
and this is my users_controller_spec.rb file:
require 'spec_helper'
describe UsersController do
render_views
describe "GET 'show'" do
before(:each) do
#user = Factory(:user)
end
it "should be successful" do
get :show, :id => #user
response.should be_success
end
here is my Gemfile, if it helps:
source 'http://rubygems.org'
gem 'rails', '3.0.1'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3-ruby', :require => 'sqlite3'
gem 'gravatar_image_tag'
group :development do
gem 'rspec-rails'
gem 'annotate-models'
end
group :test do
gem 'rspec'
gem 'webrat'
gem 'spork'
gem 'factory_girl_rails'
end
As per the latest version of Factory Girl (currently v4.0.0)
rewrite factories.rb
FactoryGirl.define do
factory :user do
name "Michael Hartl"
email "mhartl#example.com"
password "foobar"
password_confirmation "foobar"
end
end
then call it from your users controller specs as:
FactoryGirl.create(:user)
I got this exact same error message. I just restarted my Spork server and Autotest and everything went green for me.
Maybe you should try the new syntax (see github readme of factory girl)
FactoryGirl.define :user do |user|
user.name "Michael Hartl"
user.email "mhartl#example.com"
user.password "foobar"
user.password_confirmation "foobar"
end
In your spec use
#user = FactoryGirl(:user)
instead of
#user = Factory(:user)
I had this problem, but it was because I had placed the factory girl gem under the development section instead of the test section of the Gemfile. Once under the test section, it worked. One difference I note between my entry and yours is that mine specifies 1.0:
group :test do
gem 'rspec-rails', '2.6.1'
gem 'webrat', '0.7.1'
gem 'factory_girl_rails', '1.0'
end
For me I had to add require 'factory_girl' to test_helper.rb
My solution: I've accidentally included it in the :development block, and simply had to move it to the :test block
(I've listed it here, because it might help someone who doesn't follow the tutorial correctly)
I have done so,
add require 'factory_girl' to test_helper.rb and
#user = FactoryGirl.create(:user)
For those finding this page now: note where you once used "FactoryGirl" you must now use "FactoryBot" in your tests. From the thoughtbot announcement page:
"We’re renaming factory_girl to factory_bot (and factory_girl_rails to
factory_bot_rails). All the same functionality of factory_girl, now
under a different name."
More details here:
https://robots.thoughtbot.com/factory_bot
I was determined to use the newest version of Factory Girl, so I tried to adapt the code. Didn't work for me, so I used
gem 'factory_girl_rails', '1.0'
in the Gemfile to lock the version at 1.0
bundle update
restart spork and autotest and it worked.

Resources