RSpec fixtures not loading - ruby-on-rails

I am taking over a code base and am trying to run the tests. I am
somewhat new to RSpec so this might be a trivial problem.
Basically I can tell that the fixtures are not getting loaded. All 100
tests fail with a similar error.
But I don't know why. Below is the code. Where can I start looking?
In spec_helper.rb, which I know is running, I see:
Spec::Runner.configure do |config|
config.global_fixtures = :all
end
One of the tests in spec/controllers/downloads_controller_spec.rb
is below. I know it is running and I know that before the 'describe',
Partner.count == 0, so no fixture.
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe DownloadsController do
integrate_views
describe "when PDF is ready" do
before(:each) do
#registrant = Factory.create(:step_5_registrant)
stub(#registrant).merge_pdf { `touch #{#registrant.pdf_file_path}`
}
#registrant.generate_pdf
#registrant.save!
end
it "provides a link to download the PDF" do
get :show, :registrant_id => #registrant.to_param
assert_not_nil assigns[:registrant]
assert_response :success
assert_template "show"
assert_select "span.button a[target=_blank]"
assert_select "span.button a[onclick]"
end
after(:each) do
`rm #{#registrant.pdf_file_path}`
end
end
And here is what in various directories:
spec/fixtures/partners.yml - which contains 2 yaml records:
sponsor:
id: 1
username: rtv
email: rocky#example.com
crypted_password:
"c8e5b51b237344fe0e72539af0cac7197f094a5e933ffacf6e7fa612363c5933f520710c6427ac31fc4c68a2d7bb48eae601c74b96e7838f9ca1a0740b67576a"
password_salt: "Y4PPzYx2ert3vC0OhEMo"
name: Rocky
organization: Rock The Vote
url: http://rockthevote.com
address: 123 Wherever
city: Washington
state_id: 9
zip_code: 20001
phone: 555-555-1234
survey_question_1_en: "What school did you go to?"
survey_question_2_en: "What is your favorite musical group?"
created_at: <%= Time.now %>
updated_at: <%= Time.now %>
# TODO: remove partner 2 in production
partner:
id: 2
username: bull_winkle
email: bull_winkle#example.com
crypted_password:
"c8e5b51b237344fe0e72539af0cac7197f094a5e933ffacf6e7fa612363c5933f520710c6427ac31fc4c68a2d7bb48eae601c74b96e7838f9ca1a0740b67576a"
password_salt: "Y4PPzYx2ert3vC0OhEMo"
name: Bullwinkle
organization: Bullwinkle, Inc.
url: http://example.com
address: 123 Wherever
city: Washington
state_id: 9
zip_code: 20001
phone: 555-555-1234
survey_question_1_en: "What school did you go to?"
survey_question_2_en: "What is your favorite musical group?"
created_at: <%= Time.now %>
updated_at: <%= Time.now %>

Maybe this is done automatically now and you have solved it, but have you checked that your "spec/spec_helper.rb" contains:
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
Cheers

Related

How can I create new book and assign two authors with it using Rails miniTest?

Doing TDD
I facing a problem creating a book and assigning two authors with it. There is a failure in the creation. It says that there is an AssociationTypeMismatch: Author(#15100) expected, got nil which is an instance of NilClass(#40. I suppose that the format "authors: []" is not have been read well by something.
This is the test:
def test_has_many_and_belongs_to_mapping
apress = Publisher.find_by(name: 'Apress')
assert_equal 2, apress.books.size
book = Book.new(
title: 'Rails E-Commerce 3nd Edition',
authors: [
Author.find_by(first_name: 'Christian', last_name: 'Hellsten'),
Author.find_by(first_name: 'Jarkko', last_name: 'Laine')
],
published_at: Time.now,
isbn: '123-123-123-x',
blurb: 'E-Commerce on Rails',
page_count: 300,
price: 30.5
)
# apress.books << book
# apress.reload
# book.reload
# assert_equal 3, apress.books.size
# assert_equal 'Apress', book.publisher.name
end
This is the error:
MY ERD:
My schema:
I think what you are missing is a meaningful setup of data needed before this test runs. Even though those publishers and books may exist in your development environment/database, the test suite usually is configured to wipe the database clean between runs.
If you have fixtures defined, then you can reference them like this:
test/fixtures/publishers.yml
apress:
id: 1
name: Apress
test/fixtures/authors.yml
hellsten:
id: 1
first_name: Christian
last_name: Hellsten
laine:
id: 2
first_name: Jarkko
last_name: Laine
test/fixtures/books.yml
beginning_ruby:
title: Beginning Ruby
publisher_id: 1
ruby_recipes:
title: Ruby Recipes
publisher_id: 1
So that the test would look more like this:
def test_has_many_and_belongs_to_mapping
apress = publishers(:apress)
assert_equal 2, apress.books.size
book = Book.new(
title: 'Rails E-Commerce 3nd Edition',
authors: [
Author.find_by(first_name: 'Christian', last_name: 'Hellsten'),
Author.find_by(first_name: 'Jarkko', last_name: 'Laine')
],
published_at: Time.now,
isbn: '123-123-123-x',
blurb: 'E-Commerce on Rails',
page_count: 300,
price: 30.5
)
apress.books << book
apress.reload
book.reload
assert_equal 3, apress.books.size
assert_equal 'Apress', book.publisher.name
end
Or instead of using fixtures, you could create the content before the test:
So that the test would look more like this:
setup do
publisher = Publisher.create!(name: 'Apress')
publisher.books.create!(title: 'Beginning Ruby')
publisher.books.create!(title: 'Ruby Recipes')
Author.create!(first_name: 'Christian', last_name: 'Hellsten')
Author.create!(first_name: 'Jarkko', last_name: 'Laine')
end
def test_has_many_and_belongs_to_mapping
apress = Publisher.find_by(name: 'Apress')
assert_equal 2, apress.books.size
book = Book.new(
title: 'Rails E-Commerce 3nd Edition',
authors: [
Author.find_by(first_name: 'Christian', last_name: 'Hellsten'),
Author.find_by(first_name: 'Jarkko', last_name: 'Laine')
],
published_at: Time.now,
isbn: '123-123-123-x',
blurb: 'E-Commerce on Rails',
page_count: 300,
price: 30.5
)
apress.books << book
apress.reload
book.reload
assert_equal 3, apress.books.size
assert_equal 'Apress', book.publisher.name
end
That way your database has those values, and your find_by() calls should return data, and not nil.

RSpec controller GET #index test is returning an empty ActiveRecord array instead of my model

Please excuse my rustiness, first time touching Rails and this project in quite some time.
Ruby Version: 2.5.0
Rails Version: 5.1.7
RSpec Version: 3.9.3
FactoryBot Version: 6.2.0
This is my scripts_controller_spec.rb file with model creation and the test in question:
require 'rails_helper'
describe ScriptsController, type: :controller do
userID_1 = User.create!(
email: 'ueferfrfrf#u1.com',
password: 'useruser',
password_confirmation: 'useruser'
)
script1 = Script.create!(
name: 'YWoodcutter',
skill: 'Woodcutting',
bot_for: 'TRiBot',
game_for: 'Oldschool Runescape 07',
user_id: userID_1.id
)
script1.save
describe "GET #index" do
it "assigns #scripts" do
get :index
p script1
expect(assigns(:scripts)).to eq([script1])
end
end
When running the tests, the print line above outputs this, as expected:
#<Script id: 1, name: "YWoodcutter", skill: "Woodcutting", bot_for: "TRiBot", game_for: "Oldschool Runescape 07", user_id: 1, created_at:
"2021-10-19 08:29:43", updated_at: "2021-10-19 08:29:43">
However, I get this test failure:
Failures:
ScriptsController GET #index assigns #scripts
Failure/Error: expect(assigns(:scripts)).to eq([script1])
expected: [#<Script id: 1, name: "YWoodcutter", skill: "Woodcutting", bot_for: "TRiBot", game_for: "Oldschool Runescape 07",
user_id: 1, created_at: "2021-10-19 08:29:43", updated_at: "2021-10-19
08:29:43">]
 
got: #<ActiveRecord::Relation []>
(compared using ==)
My scripts_controller.rb index function looks like so:
class ScriptsController < ApplicationController
def index
#scripts = Script.order(:created_at)
end
Let me know if you need any more info, and thanks for your help!
I think the Script object is not getting created before calling the index action. Because of this, you are getting the empty ActiveRecord::Relation. In this situation let! should fix your problem
require 'rails_helper'
describe ScriptsController, type: :controller do
let!(:user_1) do
User.create!(
email: 'ueferfrfrf#u1.com',
password: 'useruser',
password_confirmation: 'useruser'
)
end
let!(:script1) do
Script.create!(
name: 'YWoodcutter',
skill: 'Woodcutting',
bot_for: 'TRiBot',
game_for: 'Oldschool Runescape 07',
user_id: user_1.id
)
end
describe "GET #index" do
before { get :index }
it "assigns #scripts" do
expect(assigns(:scripts)).to eq([script1])
end
end
end
Based on the current code, it seems you were not calling all script.
Using
### Controller
#scripts = Script.all.order(:created_at)
### Test
## Should use factories to create the records
let(:user) do
create(:user, email: 'ueferfrfrf#u1.com',
password: 'useruser',
password_confirmation: 'useruser')
end
let(:script) do
create(:script, name: 'YWoodcutter',
skill: 'Woodcutting',
bot_for: 'TRiBot',
game_for: 'Oldschool Runescape 07',
user: user)
end
should fix it.

Rails 5: How do I point fixtures to other fixtures?

I three models Comment, User and Project. Project and Comment need to point to other objects in order to be valid. For example, a comment needs to point to an author (user) and a project.
The associated fixture files look like this:
# comments.yml
test_comment:
author: users(:test_user)
project: projects(:test_project)
# users.yml
test_user:
name: 'test user'
# projects.yml
test_project:
name: 'Test'
description: 'This is a test'
owner: users(:test_user)
However, I've found that my fixtures are probably set up incorrectly. Rails returns false if I try to save the comment:
assert_equal true, comments(:test_comment)
#=> false
I can see that there are foreign keys for a project and author:
=> #<Comment:0x00007f9b1661f3d8
id: 137725605,
body: "",
project_id: 745075726,
author_id: "31ceee04-5307-5059-91db-0dc2068a780c",
created_at: Fri, 22 Feb 2019 13:17:58 UTC +00:00,
updated_at: Fri, 22 Feb 2019 13:17:58 UTC +00:00>
But when I interrogate them, Rails returns nil.
> comments(:test_comment).author
=> nil
> comments(:test_comment).project
=> nil
I expected that one would return users(:test_user) and the other would return projects(:test_project). I thought perhaps I needed to use ERB in my yaml:
test_comment:
author: <%= users(:test_user) %>
project: <%= projects(:test_project) %>
But that results is a stream of errors when I run my tests:
NoMethodError: undefined method `users' for #<#<Class:0x00007f9b17692ff8>:0x00007f9b17692dc8>
What do I need to do to point fixtures to other fixtures? Can it be done? What have I done wrong?
In the Rails guide on Testing with YAML fixtures, you can see that you don't need users(:test_user) to refer to some other object. Instead, you can simply write test_user:
# comments.yml
test_comment:
author: test_user
project: test_project
# users.yml
test_user:
name: 'test user'
# projects.yml
test_project:
name: 'Test'
description: 'This is a test'
owner: test_user
Hope this helps!

Default_scope in Rails model when testing with Rspec using FactoryGirl

I'm developing a blog in Rails and I'm stuck when I was trying to test the default scope I added to the Post model in order to have the posts in descending order of their creation date.
Post code:
class Post < ActiveRecord::Base
attr_accessible :content, :name, :title
validates :title, presence: true,uniqueness: true
validates :name, presence: true
validates :content, presence: true
default_scope order: "posts.created_at DESC"
end
Rspec code:
describe "Posts descending order of creation date" do
let(:older_post) do
FactoryGirl.create(:post, created_at: 1.day.ago)
end
let(:newer_post) do
FactoryGirl.create(:post, created_at: 1.hour.ago)
end
it "should have the 2 posts in desc order" do
Post.all.should == [newer_post, older_post]
end
end
FactoryGirl definition
FactoryGirl.define do
factory :post do
sequence(:title) { |n| "A book #{n}" }
name "Johnny"
content "Lorem Ipsum"
end
end
The output
.....F...
Failures:
1) Post Posts descending order of creation date should have the 2 posts in desc order
Failure/Error: Post.all.should == [newer_post, older_post]
expected: [#<Post id: 1, name: "Johnny", title: "A book 1", content: "Lorem Ipsum", created_at: "2013-05-01 14:44:45", updated_at: "2013-05-01 15:44:45">, #<Post id: 2, name: "Johnny", title: "A book 2", content: "Lorem Ipsum", created_at: "2013-04-30 15:44:45", updated_at: "2013-05-01 15:44:45">]
got: [] (using ==)
Diff:
## -1,3 +1,2 ##
-[#<Post id: 1, name: "Johnny", title: "A book 1", content: "Lorem Ipsum", created_at: "2013-05-01 14:44:45", updated_at: "2013-05-01 15:44:45">,
- #<Post id: 2, name: "Johnny", title: "A book 2", content: "Lorem Ipsum", created_at: "2013-04-30 15:44:45", updated_at: "2013-05-01 15:44:45">]
+[]
# ./spec/models/post_spec.rb:54:in `block (3 levels) in <top (required)>'
Finished in 1.03 seconds
9 examples, 1 failure
Failed examples:
rspec ./spec/models/post_spec.rb:53 # Post Posts descending order of creation date should have the 2 posts in desc order
I also want to mention that when I type Post.all in the Rails console, I get the records in descending order ( so as I wanted them).
Can someone give me a suggestion on what the problem might be?
Please know that let is evaluated lazily in RSpec. This often creates problem in such scenarios where ordering is concerned.
Try these two alternatives:
describe "Posts descending order of creation date" do
let!(:older_post) do
FactoryGirl.create(:post, created_at: 1.day.ago)
end
let!(:newer_post) do
FactoryGirl.create(:post, created_at: 1.hour.ago)
end
it "should have the 2 posts in desc order" do
Post.all.should == [newer_post, older_post]
end
end
Note, the use of let! instead of let.
Or, use before as:
describe "Posts descending order of creation date" do
it "should have the 2 posts in desc order" do
#older_post = FactoryGirl.create(:post, created_at: 1.day.ago)
#newer_post = FactoryGirl.create(:post, created_at: 1.hour.ago)
Post.all.should == [#newer_post, #older_post]
end
end
Do let me know if it works or not. :)

Using RSpec to test for correct order of records in a model

I'm new to rails and RSpec and would like some pointers on how to get this test to work.
I want emails to be sorted from newest to oldest and I'm having trouble testing this.
I'm new to Rails and so far I'm having a harder time getting my tests to work then the actual functionality.
Updated
require 'spec_helper'
describe Email do
before do
#email = Email.new(email_address: "user#example.com")
end
subject { #email }
it { should respond_to(:email_address) }
it { should respond_to(:newsletter) }
it { should be_valid }
describe "order" do
#email_newest = Email.new(email_address: "newest#example.com")
it "should have the right emails in the right order" do
Email.all.should == [#email_newest, #email]
end
end
end
Here is the error I get:
1) Email order should have the right emails in the right order
Failure/Error: Email.all.should == [#email_newest, #email]
expected: [nil, #<Email id: nil, email_address: "user#example.com", newsletter: nil, created_at: nil, updated_at: nil>]
got: [] (using ==)
Diff:
## -1,3 +1,2 ##
-[nil,
- #<Email id: nil, email_address: "user#example.com", newsletter: nil, created_at: nil, updated_at: nil>]
+[]
# ./spec/models/email_spec.rb:32:in `block (3 levels) in <top (required)>'
In your code:
it "should have the right emails in the right order" do
Email.should == [#email_newest, #email]
end
You are setting the expectation that the Email model should be equal to the array of emails.
Email is a class. You can't just expect the class to be equal to an array. All emails can be found by using all method on class Email.
You must set the expectation for two arrays to be equal.
it "should have the right emails in the right order" do
Email.order('created_at desc').all.should == [#email_newest, #email]
end
It should work like this.
For newer version of RSpec:
let(:emails) { ... }
it 'returns emails in correct order' do
expect(emails).to eq(['1', '2', '3'])
end

Resources