当前位置: 首页 > 知识库问答 >
问题:

为什么rspec从类似的控制台操作中得到不同的结果?(M. Hartl Ruby on Rails教程第二版-第6.3.4节)

韦原
2023-03-14

我对M. Hartl的Rails教程第6.3.4节末尾的用户模型RSpec测试有问题。我完全迷路了,请帮助。

所有的测试都通过了,除了一个我需要帮助的问题:

我的问题:为什么rspec从类似的控制台操作中得到不同的结果,我如何解决这个问题并通过测试?

失败:

1)使用有效密码验证方法的用户返回值

失败/错误:it { should = = found _ User . authenticate(@ User . password)}预期:用户id: 1,姓名:“示例用户”,电子邮件:“user@example.com”,created _ at:“2013-08-21 21:38:32”,updated _ at:“2013-08-21 21:38:32”,password _ digest:“$ 2a $ 04 $ tjct i4 yeyfujbbz 9 sa。z9 . F/kxjthu 3a 8 ONU 1 fho VN 3 x……”

在0.64049秒内完成20个示例,1个失败

失败的例子:

RSpec./规范/模型/user_spec.rb:100#使用有效密码验证方法的用户返回值

当我在rails控制台中手动测试它时,authenticate方法返回完全相同的用户,所有字段都匹配。以下是我的控制台实验:

在沙盒中加载开发环境(Rails 4.0.0)您所做的任何修改都将在退出时回滚irb(main):001:0

user = User.new(名称:“示例用户”,电子邮件:“user@example.com”,密码:“foobar”,password_confirmation:“foobar”)

=

irb(主):002:0

SQL(48.2ms)插入“用户”(“created_at”,“email”,“name”,“password_digest”,“updated_at“)值(?,?,??,?)[[“created_at”,星期三,2013年8月21日21:45:13 UTC 00:00],[“电子邮件”,“user@example.com“],[”name“,”示例用户“],“password_digest”,“$2a$10$6tJCohmi7t3OShf/55S5Se98JWvGhJfC1wNAZsc8B6WPP1Zgee0wu”],[“updated_at”,周三,2013年8月21日21:45:13 UTC 00:00]]

(0.2毫秒)释放保存点active_record_1 =

irb(主):003:0

用户负载(0.5ms)选择“用户”。*从“用户”到“用户”。“电子邮件”='user@example.com'限制1=

IRB(主):004:0

=

这是spec/models/user_spec.rb中的内容

require 'spec_helper'

describe User do

  before { @user = User.new(name: "Example User", email: "user@example.com", password: "foobar", password_confirmation: "foobar") }

  subject { @user }
.
.
.

  describe "return value of authenticate method" do
    before { @user.save }
    let(:found_user) { User.find_by_email(@user.email) }

    describe "with valid password" do
      it { should == found_user.authenticate(@user.password) }
    end

    describe "with invalid password" do
      let(:user_for_invalid_password) { found_user.authenticate("invalid") }

      it { should_not == user_for_invalid_password }
      specify { user_for_invalid_password.should be_false }
    end
  end

.
.
.
end

用户模型如下

class User < ActiveRecord::Base

  before_save { |user| user.email = email.downcase }

  validates :name, presence: true, length: { maximum: 50 }

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }

  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }
  validates :password_confirmation, presence: true

end

不确定宝石是否重要,以下是我的:

source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.0.0'

group :development do
  gem 'annotate', '~> 2.4.1.beta'
end

# Use sqlite3 as the database for Active Record
gem 'sqlite3'

# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0'

# Bootstrap css framework from Twitter
gem 'bootstrap-sass', '2.0.0'

# RSpec testing framework
gem 'rspec-rails', '2.11.0'
gem 'capybara', '2.1.0'

# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'

# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'

# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'

# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'

# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 1.2'

group :doc do
  # bundle exec rake doc:rails generates the API under doc/api.
  gem 'sdoc', require: false
end

# Use ActiveModel has_secure_password
gem 'bcrypt-ruby', '3.0.1'

提前谢谢你,如果我错过了任何其他重要的信息,请告诉我。

共有1个答案

麹正业
2023-03-14

您遇到的直接问题是如何设置测试。主题被设置为对象的未保存实例化。如果您在@user.save之后{subject.reload}之前执行,那么它会解决这个问题。这实际上只是一个创可贴。

真正的问题是你过于复杂化了你的规范。你在三个不同的地方以三种不同的方式在三种不同状态下设置同一个用户。这不应该发生。

以下是我如何设置的:

require 'spec_helper'

describe User do    
  describe "#authenticate" do
    let(:user) { User.new(name: "Example User", email: "user@example.com", password: "foobar", password_confirmation: "foobar") }

    it "has a valid password" do
      user.authenticate("foobar").should be_true
    end

    it "has invalid password" do
      user.authenticate("invalid").should be_false
    end
  end
end

只需要记住几条。

创建尽可能少的对象:创建的对象越多,就越有可能不需要或处于糟糕状态,并且测试失败,甚至更糟糕的是,您的测试很脆弱,并且意外失败。

单行< code>it很好,但是有局限性:单行< code>it块在您需要进行一些快速验证时非常有用,但是您应该谨慎使用它们。如果你发现你在一个< code>describe中包装了一个< code>it块,那么去掉那个< code>describe

保持简单:尽量不要预先加载你的测试。当您预先加载时,您很可能正在编写符合数据的测试。

在http://betterspecs.org/.还有很多其他很棒的技巧,绝不是把它当成法律,但是它确实有一些关于为编写规范奠定一个非常好的基础的好信息。

最后,祝你好运,享受写规格!

 类似资料: