FactoryGirl,Rspec,let和之前的问题

时间:2012-08-30 18:03:50

标签: ruby-on-rails rspec

我第一次使用其中一些工具。我已经阅读了文档,但想在这里问到我正在努力实现的目标。

我有一组用户,我想测试一些我可以在控制器规范中执行的操作。创建每个用户时,会发生一组回调以创建关联对象。

我想访问这些用户实例以及该ActiveRecord类的关联对象。例如,用户将拥有一组列表,因此我希望能够调用user1.lists。

另外,我想在顶部隔离这个设置并使用let或者之前的黑色。似乎只是这样调用let:

# will test that get_count_for_list will return 5
describe ApiController do

  # why same name - seems really confusing!
  let(:user) { FactoryGirl.create(:user) }
  let(:user2) { FactoryGirl.create(:user2) }

不会调用关联的回调。它是否正确?或者它可能是一个时间问题?

我喜欢使用let并能够在我的ExampleGroups中访问这些对象的语法,例如user.id但无法访问user.lists。目前我正在做类似的事情:

# will test that get_count_for_list will return 5

describe ApiController do

  # why same name - seems really confusing!
  let(:user) { FactoryGirl.create(:user) }
  let(:user2) { FactoryGirl.create(:user2) }
  let(:user3) { FactoryGirl.create(:user3) }

  before do
    FactoryGirl.create(:user2)
    FactoryGirl.create(:user3)
  end

但是觉得必须有更好的方法。我是否创建了这两个用户?

THX

编辑1

我已经在这里找到了有问题的代码。 global_id值是通过回调创建的。它在数据库中正确存在,可以通过相应的find_by_email访问,但使用user2 var不提供访问权限。

require 'spec_helper'

# will test that get_count_for_list will return 5
describe ApiController do
  # why same name - seems really confusing!
  let!(:user) { FactoryGirl.create(:user) }
  let!(:user2) { FactoryGirl.create(:user2) }
  let!(:user3) { FactoryGirl.create(:user3) }



  before do
    session[:user_id]=user.id # works
  end

  describe 'FOLLOW / UNFOLLOW options' do
    it 'shall test the ability to follow another user' do
      puts "user1: " + user.global_id.to_s # doesn't output anything
      u2=User.find_by_email('jo@jo.com') # corresponds to user2
      post :follow, :global_id => user2.global_id # doesn't work
      #post :follow, :global_id => u2.global_id  #works


      u3=User.find_by_email('su@su.com')
      puts "user_3" + u3.global_id.to_s # outputs correct value

      post :follow, :global_id => user3.global_id  #doesn't work
      #post :follow, :global_id => u3.global_id # works


      post :unfollow, :global_id => user.following.sample(1)
      response.code.should eq('200')
    end
  end
end

2 个答案:

答案 0 :(得分:29)

检查rspec doc:https://www.relishapp.com/rspec/rspec-core/v/2-11/docs/helper-methods/let-and-let

请注意,let是惰性求值的:直到第一次调用它定义的方法时才会对它进行求值。你可以用let!在每个例子之前强制调用方法。

换句话说,如果您使用letfactory_girl,则在调用let-variable之前不会创建记录。

正确的代码是:

# will test that get_count_for_list will return 5
describe ApiController do

  # why same name - seems really confusing!
  let!(:user) { FactoryGirl.create(:user) }
  let!(:user2) { FactoryGirl.create(:user2) }

答案 1 :(得分:3)

我刚刚解决了类似的声音问题。我的用户身份验证规范没有使用'let'传递。

我破碎的规格:

describe "signin" do
  before { visit signin_path }

  describe "with valid information", :js => true do
    let(:user) { FactoryGirl.create(:user) }
    before do
      fill_in "email", with: user.email
      fill_in "password", with: user.password
      click_button "Log In"
    end
    it { should have_selector('a', text: "#{user.first} #{user.last}") }
  end
end

这不起作用。当我的会话控制器尝试对其进行身份验证时,登录身份验证失败,就好像用户记录实际上不在数据库中一样。我试着用let替换let!但这并没有解决任何问题。阅读这篇文章,以及上面的链接解释让我们!我意识到我不应该使用let来制作这个规范。现在我有一个通过规范:

describe "signin" do
  before { visit signin_path }

  describe "with valid information", :js => true do
    user = FactoryGirl.create(:user)
    before do
      fill_in "email", with: user.email
      fill_in "password", with: user.password
      click_button "Log In"
    end
    it { should have_selector('a', text: "#{user.first} #{user.last}") }
  end
end