【问题标题】:Why is my rspec test failing?为什么我的 rspec 测试失败了?
【发布时间】:2011-02-27 05:52:56
【问题描述】:

这是测试:

        describe "admin attribute" do

        before(:each) do
          @user = User.create!(@attr)
        end

        it "should respond to admin" do
          @user.should respond_to(:admin)
        end

        it "should not be an admin by default" do
          @user.should_not be_admin
        end

        it "should be convertible to an admin" do
          @user.toggle!(:admin)
          @user.should be_admin
        end
      end

这是错误:

  1) User password encryption admin attribute should respond to admin
 Failure/Error: @user = User.create!(@attr)
 ActiveRecord::RecordInvalid:
   Validation failed: Email has already been taken
 # ./spec/models/user_spec.rb:128

我认为错误可能出现在我的数据填充器代码中:

require 'faker'

namespace :db do
  desc "Fill database with sample data"
  task :populate => :environment do
    Rake::Task['db:reset'].invoke
    admin = User.create!(:name => "Example User",
                 :email => "example@railstutorial.org",
                 :password => "foobar",
                 :password_confirmation => "foobar")
    admin.toggle!(:admin)             
    99.times do |n|
      name  = Faker::Name.name
      email = "example-#{n+1}@railstutorial.org"
      password  = "password"
      User.create!(:name => name,
                   :email => email,
                   :password => password,
                   :password_confirmation => password)
    end
  end
end

请告诉我是否应该再复制我的代码。

更新:这里是 @attr 的定义位置,位于 user_spec.rb 文件的顶部:

require 'spec_helper'

describe User do

  before(:each) do
      @attr = { 
        :name => "Example User", 
        :email => "user@example.com",
        :password => "foobar",
        :password_confirmation => "foobar" 
      }
    end

【问题讨论】:

标签: ruby-on-rails ruby-on-rails-3 testing rspec


【解决方案1】:

检查以确保在您的user_spec.rb 上方没有使用相同电子邮件地址在before(:each) 块中调用User.create 的块。如果您的块嵌套不正确,您将收到此错误。例如,在 Rails 教程中,很容易意外地将 describe "admin attribute" 嵌套在使用相同 before(:each) 代码的 describe "password encryption" 块中。

【讨论】:

  • 是的,我认为你是对的,但我不知道我的嵌套哪里出了问题,所以我只是删除了 describe "admin attribute" 块中的 before(:each) 块,现在我的测试通过了
  • 在这种情况下,肯定是嵌套问题,或者您的测试不会通过,因为 @user 将是 nil。 :) 这是我的complete user_spec.rb from the tutorial,如果有帮助的话。
  • 啊,谢谢,这真的很有帮助。我在某处错过了一个愚蠢的end,它把所有东西都扔掉了。谢谢布兰登。
  • 好消息,不敢相信我会错过这个,直到我再次观看截屏视频
【解决方案2】:

尝试在 before 块中检查现有用户:

before(:each) do
  User.count.should == 0
  @user = User.create!(@attr)
end

如果失败,则存在使用相同电子邮件的另一个用户。这可能是因为另一个 before 块创建了具有相同属性的用户,或者测试数据库在失败后没有正确清除。对于后一种情况,请尝试运行 rake db:test:prepare,然后再次运行规范。

【讨论】:

    【解决方案3】:

    before( :each ) 将从@attr 创建一个新的用户对象。因此,如果@attr 没有更改其字段的值,并且您打开了验证以防止重复,那么在您的第二次测试中,您在第一次测试中创建的用户对象将与您尝试在其中创建的对象发生冲突第二次测试。

    还有其他方法可以在没有数据库的情况下测试您的模型。例如,您可以使用测试替身来创建和设置具有您想要的数据的对象,然后运行测试以查看其行为是否正确。有一本 [关于 RSpec、Cucumber 和 BDD 的好书] 可能是一个很好的来源。

    编辑:抱歉,我将before(:each) 与before(:all) 混淆了。

    【讨论】:

    • 所以我应该删除before(:each) 块?
    • 测试数据库在示例之间被重置,所以这不是原因。
    • 是的,我意识到我把 before(:each) 和 before(:all) 混淆了
    【解决方案4】:

    这似乎不是设置测试数据的理想方式。即,使用 rake 任务填充数据库。

    更标准的单元测试和 Rails 实践是同时使用 factory_girl 或 test_fixture 和事务测试夹具或 database_cleaner gem。

    阅读一些关于这些的内容,它们应该可以直接使用。它们确保您的每个 rspec 测试都是独立运行的,即使您一起运行它们也是如此。这样,一个测试的每个测试数据都不会影响另一个。

    【讨论】:

    • 顺便说一句,你仍然可以继续使用faker gem 和 factory_girl
    猜你喜欢
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 2014-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多