在工作Rails代码上获取Rspec2错误

时间:2012-06-08 22:56:13

标签: rspec2 ruby-on-rails-3.2 factory-bot

我刚刚想出如何在型号User上显示国家/地区ID号的国家/地区名称。这是我在控制器中使用的基本代码和两个视图,用于通过其ID找到User后显示名称:

@country_name = Country.find(@user.country_id).name

我正在使用Factory Girl来模拟美国境内country_id的默认值为1的用户记录。在我添加这个逻辑之前,我的Rspec2测试很干净。现在,当我运行测试时,我收到以下错误。在视图或控制器中具有类似逻辑的每个测试都会产生错误。

ActiveRecord::RecordNotFound:
   Couldn't find Country with id=1

以下是我正在进行的两项Rspec2测试:

describe "profile page" do
  let(:user) { FactoryGirl.create(:user) }
  before { visit user_path(user) }

  it { should have_selector('span',    text: user.first_name+' '+user.last_name) }
  it { should have_selector('title', text: user.first_name+' '+user.last_name) }
end

个人资料页面引用@country_name,如上所述设置。国家/地区名称会按预期显示在屏幕上。

我认为我需要以某种方式为Rspec2测试添加一些东西。我不知道该怎么做。由于@country_name是一个与User无关的实例变量,我觉得我可能需要在Rspec2文件中直接执行某些操作。

任何帮助将不胜感激。到目前为止我还没有找到这样的东西,但我会继续寻找。

2012年6月8日更新下午7:27 CDT

这是我的用户控制器逻辑。在此处添加第二行会产生RSpec2错误。我在RSpec2测试中没有改变任何东西。 show.html.erb中引用了@country_name。

def show
  @user = User.find(params[:id])
  @country_name = Country.find(@user.country_id).name
end

我决定尝试这个,但得到了同样的错误:

describe "profile page" do
  let(:user) { FactoryGirl.create(:user) }
  let(:country) { FactoryGirl.create(:country) }
  before { visit user_path(user) }

  it { should have_selector('span',    text: user.first_name+' '+user.last_name) }
  it { should have_selector('title', text: user.first_name+' '+user.last_name) }
end

我将以下内容添加到与用户工厂分开的factories.rb中。

factory :country do
  id 1
  name "CountryName"
  iso "CN"
end

同样,我的国家/地区名称的应用程序逻辑非常有用。

更新6/11/2012上午9:09 CDT

这是我的factories.db文件。 country_id在User中的默认值为1。我尝试使用country_id定义如下,没有country_id的声明。我也有没有身份证的乡村工厂。我仍然有所描述的错误。我在这里提交问题之前尝试了这个。

FactoryGirl.define do

  factory :user do
    sequence(:first_name)  { |n| "First Name #{n}" }
    sequence(:last_name)  { |n| "Last Name #{n}" }
    sequence(:username)  { |n| "Username#{n}" }
    sequence(:email) { |n| "person_#{n}@example.com" }   
    password "foobar"
    password_confirmation "foobar"
    sequence(:city) { |n| "City #{n}" } 
    sequence(:state_province) { |n| "State/Province #{n}" } 
    active_user "1"
    country_id 1

    factory :admin do
      admin true
      active_user "3"
    end

    factory :blocked do
      active_user "1"
    end

    factory :rejected do
      active_user "2"
    end

    factory :not_visible do
      active_user "3"
      visible false
    end

    factory :visible do
      active_user "3"
      visible true
    end
  end

  factory :country do
    id 1
    name "CountryName"
    iso "CN"
  end

end

更新6/11/2012 5:37 pm CDT

经过几个小时的继续搜索并完全重新启动我的计算机(叹气),我终于能够让测试工作了。我在用户工厂中用user.association:country替换了country。在描述“个人资料页面”之后,我将原来的两个陈述放回去。根据建议的更改,我现在没有错误。我想该关联将在Country中创建相应的行。

非常感谢所有的帮助。这是收到的帮助和解决这个问题的一个修改的组合。

确定如何检查更改的值.......

2012年12月12日上午10:55

看起来所有的代码更正我都可以使用@ user.country.name而没有错误。我将更改我的代码以使用此流线编码。

1 个答案:

答案 0 :(得分:2)

让我们更多地设置用于测试的变量,如果你正在使用数据库清理器或类似的东西,这些可能会在每次测试运行时在数据库中被销毁。您应该在之前的区块中设置工厂:

编辑:我刚刚意识到这可能是因为你试图通过明确输入ID来匹配记录。这不起作用(id由数据库自动设置),但是Factory Girl应该处理你的关联,看看你在设置before块时会发生什么:

before(:each) do
    country = FactoryGirl.create(:country)
    user = FactoryGirl.create(:user, country: country)
    visit user_path(user)
end

我也会删除

id 1

来自您所在国家/地区的工厂,以及在用户工厂中将country_id设置为1的行。

编辑2:您需要告诉Factory Girl您的关联,不要尝试通过明确设置id字段来设置它们,因为这不起作用。

删除

country_id 1

来自用户工厂

id 1
来自国家工厂的

,并将此行添加到用户工厂:

country

(是的,只有国家自己 - 只要工厂和协会的名称相同,工厂女孩就足够聪明地弄明白发生了什么)

顺便说一下,你可以改变这个:

@country_name = Country.find(@user.country_id).name

@country_name = @user.country.name

这不会有帮助,但它更清洁。