I am working on migrating the test suite for my project to rspec. I am getting the following error trying to access my fixtures:
undefined method `[]' for nil:NilClass
Here is an example spec file:
require 'rails_helper'
feature "edit contacts" do
fixtures :contacts
before(:all) do
#thing = contacts(:two)
end
scenario "do a thing" do
visit new_contact_path
end
end
I get the error in the before block, on the call to contacts(:two)
Here is config info from rails_helper.rb
RSpec.configure do |config|
config.infer_spec_type_from_file_location!
config.fixture_path = "#{::Rails.root}/spec/fixtures"
end
Here is version info from Gemfile.lock:
rails (4.0.13)
rspec-core (3.2.2)
rspec-expectations (3.2.0)
rspec-mocks (3.2.1)
rspec-rails (3.2.1)
rspec-support (3.2.2)
I'm happy to provide any additional supporting information if needed. Thanks for taking a look, any help appreciated!
ok - finally resolved this with the help of a coworker. The issue was that I should have been using before(:each) instead of before(:all).
Apparently, using :each triggers a 'before_setup' callback in ActiveRecord::FixtureSet which sets up all the fixtures, and :all doesn't.
According to the docs:
before(:each) blocks are run before each example before(:all) blocks are run once before all of the examples in a group
Related
I'm making RSpec test.
Our website like this. It's plain website.
https://somewebsite.com/restaurant
So every time I try to test, it shows this kind of error.
$ bundle exec rspec spec/requests/restaurant_spec.rb
Restaurants
GET /index
index responds successfully (FAILED - 1)
Failures:
1) Restaurants GET /index index responds successfully
Failure/Error: get :index
URI::InvalidURIError:
bad URI(is not URI?): http://www.example.com:80index
# ./spec/requests/restaurant_spec.rb:6:in `block (3 levels) in <top (required)>'
Finished in 0.00484 seconds (files took 6.41 seconds to load)
1 example, 1 failure
My test code is this.
require 'rails_helper'
RSpec.describe "Restaurants", type: :request do
describe "GET /index" do
it "index responds successfully" do
get :index
expect(response).to be_success
end
end
end
And my application code here.
def index
#q = Restaurant.ransack(params[:q])
if params[:q].present?
#all_restaurants = #q.result(distinct: true).page(params[:page])
else
#all_restaurants = Restaurant.page(params[:page])
end
end
BTW my routing is this.
scope "(:locale)", locale: /en|ja/ do
get 'restaurant/' => 'restaurant#index'
get 'restaurant/:id' => 'restaurant#show'
end
Why this error happens? Please let me know. Thanks in advance.
Appendix
$ ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17]
$ rails -v
Rails 5.2.2
RSpec
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-rails (5.0.1)
I think this error is related to the describe block in RSpec. Change "Restaurants" to just Restaurant (singular and without the quotation marks).
require 'rails_helper'
RSpec.describe Restaurant, type: :request do
describe "GET /index" do
it "index responds successfully" do
get :index
expect(response).to be_success
end
end
end
Also, I think you'll have to change your routes to get this to work properly. Since you have a resourceful controller, use resource routing:
scope "(:locale)", locale: /en|ja/ do
resources :restaurants, only: %i[index show]
end
Should give you the routes /restaurants and /restaurants/:id with your desired locales, which is the Rails convention for this type of routing. And it'll also allow you to use :index and :show in your RSpec tests.
Using a Grape API and add the tests in the Rakefile. Its a Rack application mounted on the main rails app.
namespace :test do
Rake::TestTask.new(:api) do |t|
t.pattern = 'test/api/**/*_test.rb'
end
end
Rake::Task[:test].enhance [ 'test:api' ]
However if I try to test it there aren't any of the controller methods.
describe API do
# get, post, patch etc all raise
end
Error below.
NoMethodError: undefined method `get' for #<#<Class:0x007fd63cdfc0e0>:0x007fd63cdc7a70>
How can I test rack apps with minitest-rails bdd?
Figured it out.
class MiniTest::Spec
include FactoryGirl::Syntax::Methods
include Rack::Test::Methods
def app
API
end
end
I'm trying to include some helpers to my test but I can't make that it works.
I got the following error:
/home/edu/.rvm/rubies/ruby-1.9.3-p392/bin/ruby -S rspec ./spec/features/customers_spec.rb ./spec/features/login_spec.rb ./spec/features/products_spec.rb ./spec/features/suppliers_spec.rb
/home/edu/Desktop/rails_proyects/gg/spec/support/features.rb:2:in `block in <top (required)>': uninitialized constant MyHelp (NameError)
from /home/edu/.rvm/gems/ruby-1.9.3-p392#gg/gems/rspec-core-2.14.6/lib/rspec/core.rb:120:in `configure'
from /home/edu/Desktop/rails_proyects/gg/spec/support/features.rb:1:in `<top (required)>'
I have this:
# spec/support/features/session_helper.rb
module MyHelp
module SessionHelpers
...
def sign_in
...
end
end
end
# spec/support/features.rb
RSpec.configure do |config|
config.include MyHelp::SessionHelpers, type: :feature
end
I'm using it here:
# spec/features/login_spec.rb
require 'spec_helper'
feature "Login" do
scenario "with valid credentials" do
user = create(:user)
sign_in user.email, user.password
page.should have_content(I18n.t('layouts.header.exit', locale: 'es'))
end
end
I'm using:
rspec (2.14.1)
rspec-core (2.14.6, 2.14.5)
rspec-expectations (2.14.3, 2.14.2)
rspec-mocks (2.14.4, 2.14.3)
rspec-rails (2.14.0)
ruby 1.9.3p392
rails 3.2.13
Can someone help me with this?
thank you.
It looks like you just need to require the new helper before you try to use it in spec/support/features.rb
require Rails.root.join('spec/support/features/session_helper')
Also, it's best practice to have your class/module match the file name, so either the file should be pluralized, or the helper singularized.
My helper code looks like this (and works fine btw):
module ProvidersHelper
def call_to_review(provider)
if user_signed_in? && review = Review.find_by_provider_id_and_user_id(provider.id, current_user.id)
link_to "Edit Your Review", edit_provider_review_path(provider, review), :class => "call_to_review"
else
link_to "Review This Provider", new_provider_review_path(provider), :class => "call_to_review"
end
end
end
Unfortunately, this produces the following error when I run my tests:
undefined method `user_signed_in?' for #<ActionView::Base:0x00000106314640>
# ./app/helpers/providers_helper.rb:3:in `call_to_review'
Clearly the Devise::Controllers::Helpers are not being included in my helpers when rspec is running the test. Any suggestions that might help this work?
Edit: to provide a bit more information, my spec_helper does have this:
config.include Devise::TestHelpers, :type => :controller
config.include Devise::TestHelpers, :type => :view
config.include Devise::TestHelpers, :type => :helper
(Sadly, I couldn't get it to work with :type => [:controller, :view, :helper])
Anyway I believe that these lines add the sign_in(scope, object) (and other) test helpers to your tests. They don't add the helpers that you would actually leverage in your controller / view code.
I think the philosophy of rspec is to test the view/helpers/models in total isolation as much as possible. So in this case, i would stub out the user_signed_in? and returns false or true and my results should change appropriately.
This gives you a clean isolated test.
Are you currently including the test Helpers as suggested in the wiki?
# spec_helper.rb:
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
type would be probably helper in your case.
Maybe try putting this is in a before block?
#request.env["devise.mapping"] = :user
This has not been solved to my satisfaction and probably never will be. I think the best work-around for now is to manually stub helper.current_user and any other Devise methods you use in the helper method you're testing.
Yes, Devise provides these stubbing facilities for controller and view specs. I suspect that it's something about the combination of Devise/Rails/Test::Unit/Rspec that proves this to be difficult for helper specs.
my helper test uses Devise and cancan and works without stubbing anything (but I'm not sure if it is better to actually stub everything).
Here's the gist: https://gist.github.com/shotty01/5317463
i also tried to add user_signed_in? in the helper method and it still was fine.
The following is required:
add to spec_helper.rb:
config.include Devise::TestHelpers, :type => :helper
My spec gems:
rspec (2.10.0)
rspec-core (2.10.1)
rspec-expectations (2.10.0)
rspec-mocks (2.10.1)
rspec-rails (2.10.1)
of course you can sign in without factory girl, you just have to rewrite the ValidUserHelper methods to create a user directly or from fixtures.
Im getting the errors below despite following the documentation.
In test_helper.rb
ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require "authlogic/test_case"
require 'test_help'
require 'shoulda'
require File.dirname(__FILE__) + "/factories"
In my functional test
require 'test_helper'
class SentencesControllerTest < ActionController::TestCase
setup do
:activate_authlogic
end
context "logged in" do
setup do
#user = Factory(:user)
UserSession.create(#user.id)
end
context "on GET to :new" do
setup do
get :new
end
should "present form with text field" do
assert_select('form#new_sentence') do
assert_select('textarea#sentence_text')
end
end
end
end #context logged in.
end
in environments.rb
config.gem "authlogic"
Im not sure why it isnt working. Can anyone help out on this?
Authlogic::Session::Activation::NotActivatedError: You must activate the Authlogic::Session::Base.controller with a controller object before creating objects
authlogic (2.1.3) lib/authlogic/session/activation.rb:47:in `initialize'
authlogic (2.1.3) lib/authlogic/session/klass.rb:64:in `initialize'
authlogic (2.1.3) lib/authlogic/session/scopes.rb:79:in `initialize'
authlogic (2.1.3) lib/authlogic/session/existence.rb:29:in `new'
authlogic (2.1.3) lib/authlogic/session/existence.rb:29:in `create'
test/functional/sentences_controller_test.rb:11:in `__bind_1270172858_922804'
shoulda (2.10.3) lib/shoulda/context.rb:380:in `call'
shoulda (2.10.3) lib/shoulda/context.rb:380:in `run_current_setup_blocks'
shoulda (2.10.3) lib/shoulda/context.rb:379:in `each'
shoulda (2.10.3) lib/shoulda/context.rb:379:in `run_current_setup_blocks'
shoulda (2.10.3) lib/shoulda/context.rb:371:in `run_all_setup_blocks'
shoulda (2.10.3) lib/shoulda/context.rb:375:in `run_parent_setup_blocks'
shoulda (2.10.3) lib/shoulda/context.rb:359:in `test: logged in on GET to :new should present form with text field. '
/opt/rubymine/rb/testing/patch/testunit/test/unit/ui/testrunnermediator.rb:36:in `run_suite'
/opt/rubymine/rb/testing/patch/testunit/test/unit/ui/teamcity/testrunner.rb:215:in `start_mediator'
/opt/rubymine/rb/testing/patch/testunit/test/unit/ui/teamcity/testrunner.rb:191:in `start'
Should:
class SentencesControllerTest < ActionController::TestCase
setup do
:activate_authlogic
end
...
be:
class SentencesControllerTest < ActionController::TestCase
def setup # setup should be its own method, prefixed with "def"
activate_authlogic # note the lack of a ":"
end
...
If, alternatively, you're following the Rails testing tutorial, it may have a single-line setup deal like:
setup :activate_authlogic # note the USE of a ":" here - not sure why it's different between this and when you put it in its own method but that might be the answer for you