FactoryGirl with Rspec in Rails Unknown Method Error - ruby-on-rails

So I am dealing with Rspec testing and FactoryGirl. I'm still a bit confused as to the inner workings of FactoryGirl when an object is created or built.
I have a few test results that look similar to this:
Failure/Error: #ticket = FactoryGirl.create(:ticket)
NoMethodError:
undefined method `user=' for #<Ticket:0x007f1455e72fc8>
# ./spec/models/ticket_spec.rb:38:in `block (3 levels) in <top (required)>'
It seems as if it is trying to assign an instance of ticket to user but why? And where would I start to try to fix it?
Update
I am just getting familiar with this code base and so I just realized there is no ticket factory or user factory. Is this way of creating a ticket for testing incorrect? Sorry for ignorance, I'm still very green with FactoryGirl and test frameworks in general.

You need to define your factories, most likely in spec/factories.rb or in a spec/factories folder. More info: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md
# spec/factories.rb
factory :user do
# assuming this passes model validations
end
factory :ticket do
# assuming this passes model validations
user
end

Related

Tests failing because a gems method is undefined

I'm writing tests for a rails application and keep getting the following error, which is related to this UK postcode validator gem:
Error:
OrganisationsControllerTest#test_0001_should get index:
NoMethodError: undefined method `full_valid?' for # <UKPostcode::GeographicPostcode:0x007fe405e6caf8>
app/validators/postcode_validator.rb:4:in `validate_each'
test/controllers/organisations_controller_test.rb:7:in `block in <class:OrganisationsControllerTest>'
The error is refering to the line where FactoryGirl instantiates and object for use in the tests. This is the factory used:
FactoryGirl.define do
factory :organisation do
name 'Acme Corp'
address_1 'Acme House'
address_2 '40 - 44 Harvard Road'
address_3 'Archingdon'
town 'Exeter'
postcode 'EX4 6PX'
phone_number '03309 890890'
email 'hello#acme.com'
linkedin_url 'https://linkedin.com/acmecorp'
twitter_handle 'acmecorp'
facebook_url 'https://facebook.com/acmecorp'
website 'https://www.acmecopr.com'
end
end
I assume the error is because I need to require the library somewhere, but I can't seem to find the right place. So far I have added require 'uk_postcode' to the file the factory is defined in, the failing controller test class and test_helper.rb.
How can I stop this error?
Any help much appreciated :)
Doesn't look like require error. It is unable to find full_valid? method on the instance of UKPostcode::GeographicPostcode object. It can be because of the version of gem you have doesn't have this method.
Look here to see how you can verify it. Open console and create a new
UKPostcode::GeographicPostcode object and verify if the method exists.

FactoryGirl: Factory not registered for Engine project

I've gone through these pages and tried many things found on those pages:
FactoryGirl: Factory not registered: user (ArgumentError)
Cannot get factory_girl running under rails 3.0.5,unexpected tCONSTANT
'Factory not registered' error in Rails 4
FactoryGirl: Factory not registered
but keep getting "Factory not registered: user"
The file test/factories.rb (also tried test/factories/user_factory.rb) looks like:
FactoryGirl.define do
factory :user do
login 'mbrown#yahoo.com'
email 'mbrown#yahoo.com'
end
end
Stub for test:
it 'just_a_test_of_testing' do
u = FactoryGirl.create(:user)
end
Doesn't work, gives me "ArgumentError: Factory not registered: user"
Does anyone know the "right solution"? It seems likely it is "engine" related, but I just don't know what to try next, any ideas? Maybe it has something to do with the fact that User is a model of the test/dummy app?
Did you configure definitions path in spec/support/factory_girl.rb file as FactoryGirl documentation suggests?
FactoryGirl.definition_file_paths = %w(custom_factories_directory)
FactoryGirl.find_definitions
A coworker got it going, his class looks like
Module MyEngineMod
FactoryGirl.define do
factory :user, class: User do
# content not shown
end
end
end
So it seems it needed to be name-spaced at least, and maybe needs the class: attribute too.

undefined local variable or method `request'

I am new to ruby on rails. I am getting an undefined method error when I run rspec on comment_spec.rb
1) after_save calls 'Post#update_rank' after save
Failure/Error: request.env["HTTP_REFERER"] = '/'
NameError:
undefined local variable or method `request' for #<RSpec::ExampleGroups::AfterSave:0x007fa866ead8d0>
# ./spec/models/vote_spec.rb:45:in `block (2 levels) in <top (required)>'
This is my spec:
require 'rails_helper'
describe Vote do
....
describe 'after_save' do
it "calls 'Post#update_rank' after save" do
request.env["HTTP_REFERER"] = '/'
#user = create(:user)
#post = create(:post, user: #user)
sign_in #user
vote = Vote.new(value:1, post: post)
expect(post). to receive(:update_rank)
vote.save
end
end
Any help that you would have would be greatly appreciated...
I was following the apirails book tutorial chapter 3 here
http://apionrails.icalialabs.com/book/chapter_three
I was receiving the same error and DrPositron's solution worked for me, all green again. Just needed to add ":type => :controller" on my block like so:
describe Api::V1::UsersController, :type => :controller do
end
Hope this helps someone
OK here's the deal.
Vote is a model, i suppose.
You are writing a test for that model.
There's a difference between model tests ("the domain logic is doing what its supposed to") and feature/integration tests ("the application is behaving the way its supposed to").
The request variable is associated with feature or controller tests.
So what's wrong?
You are not logging in users in model tests, just check if the update_rank method is being called on save, thats it.
No user-interaction jazz in model tests.
Hope that helps!
Cheers
Jan
So Louis, just to expand on Jan's response:
You appear to be writing a model spec. The purpose of a model spec is simply to test how your model classes work, and that behavior is testable without having to pay any attention to the application logic around signing in, making "requests" to particular controllers, or visiting particular pages.
You're essentially just testing a couple related Ruby classes. For this, we don't need to think about the whole app -- just the classes we're testing.
As a consequence, RSpec doesn't make certain methods available in the spec/models directory -- you're not supposed to think about requests or authentication in these tests.
It looks like your test is simply designed to make sure that when you create a vote for a post, it updates that post's rank (or, specifically, call's that post's update_rank method). To do that, you don't need to create a user, or sign a user in, or pay any attention to the request (what request would we be referring to? We're just testing this as if in Rails console, with no HTTP request involved).
So you could basically remove the first four lines of your test -- apart from the line creating your post, and the post's user if it's necessary (if the post model validates the presence of a user). Don't sign a user in -- we're just testing a Ruby class. There's no concept of a website to sign into in this test.
Then, as a last thing to take care of to get your spec to pass, make sure to refer to the post you create by the right name. Right now, you're creating a post and assigning it to the #post variable, but then you're referring to just post later on. post doesn't exist; just #post. You'll have to pick one variable name and stick with it.
Also, if you are using RSpec 3, file type inference is now disabled by default and must be opted in as described here. If you're new to RSpec, a quick overview of the canonical directory structure is here.
For example, for a controller spec for RelationshipsController, insert , :type => :controller as such:
describe RelationshipsController, :type => :controller do
#spec
end

Feature Spec passes every time in RSpec, Fails in Jenkins

I have a users factory:
FactoryGirl.define do
factory :user, :aliases => [:assignee] do
sequence(:email) { |n| "foo#{n}#example.com" }
sequence(:username) { |n| "foo#{n}#example.com" }
profile
end
end
And a jobs factory:
FactoryGirl.define do
factory :job do
association :assignee, factory: :user
description "MyText"
completion_comment "MyText"
job_type "MyString"
...
end
end
Which are loaded into my jobs_feature_spec_helper:
def add_valid_job
click_job
within("#add_job") do
select 'foo1#example.com', from: 'Assignee'
fill_in_html("job__textarea", {:with => job[:description]})
click_button "Save"
end
end
My feature page spec passes in RSpec on my machine, but my employer sent me an email saying that the spec failed in Jenkins. Here's the message he sent:
Unable to find option "foo1#example.com <mailto:foo1#example.com>"
./spec/support/job_feature_spec_helpers.rb:11:in `block in add_valid_job'
./spec/support/job_feature_spec_helpers.rb:10:in `add_valid_job'
./spec/features/jobs/edit_job_line_spec.rb:8:in `block (2 levels) in <top (required)>'
So, it appears that when Jenkins runs the spec, it's not finding the assignee from the drop-down list, yet RSpec is. I have never personally used Jenkins, so if anyone has any advice that may help, I'd appreciate hearing it. Thanks!
The problem is about the sequence number. You can't use hardcorded 'foo1#example.com' in test.
There is no guarantee that the sequence number will start from 1. I have no time to figure out the reason, but just know the fact. In my tests I often see it from tens after running several tests.
I would suggest you to get the email from an existing user in db, created by FactoryGirl.
Although this was not your issue, one possible cause of getting different results between jenkins and test environments is using different DBs on each.
In my case I was using sqlite on jenkins and postgres on test, and that was generating different results.
Locally you can run
RAILS_ENV="jenkins" bundle exec rspec
to run specs on jenkins environment.

How can I access helper methods in my decorator spec files using Draper 0.14.0

Currently in my spec/decorators/product_decorator_spec.rb, I have the following:
require 'spec_helper'
describe ProductDecorator do
let(:product) { FactoryGirl.create(:product) }
subject do
ProductDecorator.first
end
before do
product
end
it 'should render the name attribute with a link to the product page' do
subject.name.should == h.link_to(product.name, 'test')
end
end
When I run my spec I get the following:
F.....
Failures:
1) ProductDecorator should render the name attribute with a link to the product page
Failure/Error: subject.name.should == h.link_to(product.name, 'resr')
NameError:
undefined local variable or method `h' for #<RSpec::Core::ExampleGroup::Nested_2:0x007fbbf212c8b0>
# ./spec/decorators/product_decorator_spec.rb:15:in `block (2 levels) in <top (required)>'
Finished in 0.98531 seconds
6 examples, 1 failure
Failed examples:
rspec ./spec/decorators/product_decorator_spec.rb:14 # ProductDecorator should render the name attribute with a link to the product page
According to the documentation, specs placed in the decorator folder should have access to the helper method, however my spec does not. I've also tried manually tagging my specs, but doesn't seem to have any effect.
Thanks for looking.
if you want to access the helper, you can do it via your_decorator.h.link_to.
when you are setting the subject, you will need to make sure that the thing you are calling will get routed to the helper, there is nothing injected into your rspec example!
in your example it would be subject.h.link_to for calling a helper method.
i also think that there are a lot of wired things in your spec. your usage of let, subject and before are kind of disturbing for me...
here is a nice writeup about how to write clean rspec: http://eggsonbread.com/2010/03/28/my-rspec-best-practices-and-tips/
I've encountered the same issue, where calling helper methods on the decorator's helper proxy (.h) doesn't work in test (in Draper 1.3). I ended up working around it with this, though I'm not very pleased with it:
my_decorated_object.h.extend ApplicationHelper
Your mileage may vary depending on how many controller features you access in your helper.

Resources