工厂女孩没有发起对象

时间:2012-06-26 09:27:04

标签: ruby-on-rails rspec factory-bot

我想问题是我不知道如何正确使用Rspec的工厂女孩​​。或者正确地测试导轨。仍然认为它有点奇怪..

我有一个班级,用户,以下工厂:

FactoryGirl.define do
  factory :user do
    name     "admin"
    email    "admin@admin.com"
    adminstatus  "1"
    password "foobar"
    password_confirmation "foobar"
  end

  factory :user_no_admin, class: User do
    name     "user"
    email    "user@user.com"
    adminstatus  "2"
    password "foobar"
    password_confirmation "foobar"
  end
...

我的测试看起来像这样:

...
describe "signin as admin user" do
  before { visit login_path }
  describe "with valid information" do
    let(:user_no_admin) { FactoryGirl.create(:user_no_admin) }
    let(:user) { FactoryGirl.create(:user) }
    before do
      fill_in "User",    with: user.name
      fill_in "Password", with: user.password
      click_button "Login"
    end

    it "should list users if user is admin" do 
      response.should have_selector('th', content: 'Name') 
      response.should have_selector('td', content: user_no_admin.name)
      response.should have_selector('td', content: user.name)
    end
  end      
end#signin as admin user
...

基本上我试图测试一下,如果你以管理员身份登录,你应该看到所有用户的列表。我有一个测试,以便稍后在文件中以非管理员身份登录。我已经在数据库中有几个用户了。

在用户'admin'列表中,已显示已登录的用户以及已在db中的用户。但是,除非我之前做过类似的事情,否则不会显示“用户”:

fill_in "User",    with: user_no_admin.name
fill_in "Password", with: user_no_admin.password

除非我使用它,否则它将不会存在。但是,如果我使用put它会打印我正在输入的信息,即使我没有执行上面的'fill_in'。

我有一个类似的例子,其中一个帮助我。

describe "should have company name" do
  let(:company) { FactoryGirl.create(:company) }
  let(:category) { FactoryGirl.create(:category) }
  let(:company_category) { FactoryGirl.create(:company_category, company_id: company.id, category_id: category.id) }
  it "should contain companies name" do
    puts company_category.category_id
    get 'categories/' + company.categories[0].id.to_s
    response.should have_selector('h4', :content => company.name)
  end
end

如果没有上面的提示,我会得到一个

Called id for nil

在我以某种方式使用它之前,我是否必须启动(?)Factory女孩创建的对象?

需要其他任何代码?

4 个答案:

答案 0 :(得分:6)

let(:whatever) 

直到第一次调用它们时才创建对象。如果您希望在首次使用之前使用它,请使用

let!(:whatever)

代替。

或使用前一栏:

before(:each) do
  @company = FactoryGirl.create(:company)
  ....
end

在您需要使用之前会创建对象。

答案 1 :(得分:1)

而不是:

factory :user do
  name     "admin"
  email    "admin@admin.com"
  ...

我会这样做:

factory :user do |f|
  f.name "admin"
  f.email "admin@admin.com"
  ...

而不是:

let(:user_no_admin) { FactoryGirl.create(:user_no_admin) }
let(:user) { FactoryGirl.create(:user) }

我会这样做:

@user_no_admin = Factory(:user_no_admin)
@user = Factory(:user)

答案 2 :(得分:1)

我在现有的测试中遇到了类似的问题,我发现这个问题有点不同。

在这种情况下,被测控制器最初调用save!,但我将其更改为调用let,并相应地更新了测试。

修订后的测试是:

  • 将实例声明为expect_any_instance_of(MyObject).to receive(:save!)声明
  • 设定保存期望!方法(例如save!
  • 在期望之后第一次使用该实例。

在内部,似乎FactoryGirl正在调用results = [] for i in params_list1: for j in params_list2: results.append(myfunction(i,j)) 方法,并且在将期望从save更改为save!之后,实际上没有完成任何工作(并且测试中的代码无法找到实例来自DB) 我需要更新并且很难在没有黑客的情况下实际通过

答案 3 :(得分:-1)

尝试在工厂女孩中使用特质,有this link

中提到的例子