Home>

I was testing with RSpec by referring to the following page for studying and portfolio creation, but
I got stuck with the User Spec test.

Test Rails Tutorial (Chapter 7) with RSpec

I would appreciate it if you could teach me the solution.

What I did

Initially, I was angry that signup_path was undefined, but from Qiita and Stackoverflow articles, in rails_helper.rbconfig.include Rails.application.routes.url_helpersWhen I put in, the error changed and it became the current one.

Environment:
Ruby 2.7.4
Rails 6.0.3


The test part of the gemfile is below

group: development,: test do
  gem'byebug', '11 .0.1', platforms: [: mri,: mingw,: x64_mingw]
  gem'factory_bot_rails'
  gem'rspec-rails','~ >
 5.0'
  gem'shoulda-matchers'
  gem'sqlite3', '1.4.2'
end
group: test do
  gem'capybara', '3.28.0'
  gem'guard', '2.16.2'
  gem'guard-minitest', '2.4.6'
  gem'minitest', '5.11.3'
  gem'minitest-reporters', '1.3.8'
  gem'rails-controller-testing', '1.0.4'
  gem'selenium-webdriver', '3.142.4'
  gem'webdrivers', '4.1.2'
end

The main contents of rails_helper.rb

require'spec_helper'
ENV ['RAILS_ENV'] ||='test'
require File.expand_path ('../config /environment', __dir__)
abort ("The Rails environment is running in production mode!") if Rails.env.production?
require'rspec /rails'
begin begin
  ActiveRecord :: Migration.maintain_test_schema!
rescue ActiveRecord :: PendingMigrationError= >
 e
  puts e.to_s.strip
  exit 1
end
# Read the method in capybara
require'capybara /rspec'
RSpec.configure do | config |
  config.fixture_path= "# {:: Rails.root} /spec /fixtures"
  config.use_transactional_fixtures= true
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!
  config.include FactoryBot :: Syntax :: Methods
  config.before (: each, type :: system) do
    driven_by: selenium_chrome_headless
  end
  config.include ApplicationHelper
  # Signup_path was said to be undefined so I put it in
  config.include Rails.application.routes.url_helpers
  # Force Capybara :: DSL to load
  config.include Capybara :: DSL
end
Shoulda :: Matchers.configure do | config |
  config.integrate do | with |
    with.test_framework: rspec
    with.library: rails
  end
end

The contents of spec /factories /users.rb

FactoryBot.define do
  factory: user do
    name {'Example User'}
    sequence (: email) {| n | "user_ # {n} @ example.com"}
    password {'password'}
    password_confirmation {'password'}
  end
end

This is the relevant part of the problem spec /models/user_spec.rb

require'rails_helper'
RSpec.describe User, type :: model do
  # Test if factory bot exists
  it'has a valid factory bot' do
    expect (build (: user)). to be_valid
  end
(Omitted)
  describe'POST # create' do
    # Valid user verification
    context'valid request' do
      # User added
      it'adds a user' do
        expect do
          # The post below is said to be undefined
          post signup_path, params: {user: attributes_for (: user)}
        end.to change (User,: count) .by (1)
      end
      # Verification when a user is added
      context'adds a user' do
The post below is said to be undefined.
        before {post signup_path, params: {user: attributes_for (: user)}}
        subject {response}
        # Redirected to show page
        it {is_expected.to redirect_to user_path (User.last)}
        # Successful redirect
        it {is_expected.to have_http_status 302}
      end
    end
    # Invalid request
    context'invalid request' do# Create invalid data let (: user_params) do
        attributes_for (: user, name:'',
                              email:'user @ invalid',
                              password:'',
                              password_confirmation:'')
      end
      # Verification that no user is added
      it'does not add a user' do
        expect do
The post below is said to be undefined.
          post signup_path, params: {user: user_params}
        end.to change (User,: count) .by (0)
      end
    end
  end
end

The error contents displayed in the terminal are as follows.

User
  has a valid factory bot
  validations
    is expected to validate that: name cannot be empty /falsy
    is expected to validate that: email cannot be empty /falsy
    is expected to validate that the length of: name is at most 50
    is expected to validate that the length of: email is at most 255
    is expected to allow: email to be ‹" [email protected]" ›, ‹"[email protected] "›, ‹"[email protected]" ›, ‹"[email protected] org "›, or ‹" alice + [email protected] "›
    is expected not to allow: email to be ‹"[email protected],com"›, ‹"user_at_foo.org" ›, ‹"[email protected]"›, ‹"[email protected]_baz.com" ›, or ‹ "[email protected]+baz.com" ›
    validate uniqueness of email
      is invalid with a duplicate email
  before_save
    # Email_downcase
      makes email to low case
  validatetions
    is expected to validate that the length of: password is at least 6
    validate presence of password
      is invalid with a blank password
  POST # create
    valid request
      adds a user (FAILED -1)
      adds a user
        example at ./spec/models/user_spec.rb:73 (FAILED-2)
        example at ./spec/models/user_spec.rb:75 (FAILED --3)
    invalid request
      does not add a user (FAILED-4)
Failures:
  1) User POST # create valid request adds a user
     Failure /Error: post signup_path, params: {user: attributes_for (: user)}
     NoMethodError:
       undefined method `post'for # <
RSpec :: ExampleGroups :: User :: POSTCreate :: ValidRequest: 0x00007fa90a96e0f0 >
     # ./Spec/models/user_spec.rb:65: in `block (5 levels) in <
main >
'
     # ./Spec/models/user_spec.rb:64: in `block (4 levels) in <
main >
'
  2) User POST # create valid request adds a user
     Failure /Error: before {post signup_path, params: {user: attributes_for (: user)}}
     NoMethodError:
       undefined method `post'for # <
RSpec :: ExampleGroups :: User :: POSTCreate :: ValidRequest :: AddsAUser: 0x00007fa90a98e828 >
     # ./Spec/models/user_spec.rb: 70: in `block (5 levels) in <
main >
'
  3) User POST # create valid request adds a user
     Failure /Error: before {post signup_path, params: {user: attributes_for (: user)}}
     NoMethodError:
       undefined method `post'for # <
RSpec :: ExampleGroups :: User :: POSTCreate :: ValidRequest :: AddsAUser: 0x00007fa8fe3e9988 >
     # ./Spec/models/user_spec.rb: 70: in `block (5 levels) in <
main >
'
  4) User POST # create invalid request does not add a user
     Failure /Error: post signup_path, params: {user: user_params}
     NoMethodError:
       undefined method `post'for # <
RSpec :: ExampleGroups :: User :: POSTCreate :: InvalidRequest: 0x00007fa8fe3f00d0 >
     # ./Spec/models/user_spec.rb: 90: in `block (5 levels) in <
main >
'
     # ./Spec/models/user_spec.rb:89: in `block (4 levels) in <
main >
'
Finished in 0.39295 seconds (files took 2.59 seconds to load)
15 examples, 4 failures
Failed examples:
rspec ./spec/models/user_spec.rb:63 # User POST # create valid request adds a user
rspec ./spec/models/user_spec.rb:73 # User POST # create valid request adds a user
rspec ./spec/models/user_spec.rb:75 # User POST # create valid request adds a user
rspec ./spec/models/user_spec.rb:88 # User POST # create invalid request does not add a user
  • Answer # 1

    This test is a unit test of the model ( model spec) Is expected to be done. On the other hand, prepare for RSpecpostDSLs such as are expected to be used in request specs.

    RSpec.describe User, type :: model do
                               ^^^^^^ Here
    

    Therefore, the remedy depends on what kind of test you wanted to do.

    If you want to unit test your model,postIs strange to use. Just call the model method and check its behavior.

    If you want to do integration testing including routing, that is, request spec, please review the way of defining the test as described in the document.

    Thank you for your advice. The cause was that the test that was originally written in the requests file (spec /requests /accesses_to_users_spec.rb) was written in the model file (spec_models /users.rb). I was able to confirm that the test passed after the correction.

    モジャルダー2021-09-24 00:52:58
  • Answer # 2

    This test is a unit test of the model ( model spec) Is expected to be done. On the other hand, prepare for RSpecpostDSLs such as are expected to be used in request specs.

    RSpec.describe User, type :: model do
                               ^^^^^^ Here
    

    Therefore, the remedy depends on what kind of test you wanted to do.

    If you want to unit test your model,postIs strange to use. Just call the model method and check its behavior.

    If you want to do integration testing including routing, that is, request spec, please review the way of defining the test as described in the document.

    Thank you for your advice. The cause was that the test that was originally written in the requests file (spec /requests /accesses_to_users_spec.rb) was written in the model file (spec_models /users.rb). I was able to confirm that the test passed after the correction.

    モジャルダー2021-09-24 00:52:58