使用Rails上的Rspec测试在回调上创建关联对象

时间:2011-10-26 10:54:02

标签: ruby-on-rails rspec

试图围绕rspec和正确的测试,并且有一些困难时间正确地执行以下操作

假设我们有三个类,如

Class User
    belongs_to :company
    has_and_belongs_to_many :roles
end

Class Company
    has_many :users
end

Class Role
    has_and_belongs_to_many :users
end

在User类中,我有before_create回调,指定用户默认的'company_admin'角色,如果用户是第一个与公司关联的用户

def check_for_initial_company_admin_role
  if self.company.users.count == 0
    self.roles << Role.find_by_name("company_admin")
  end
end

如何在我的模型规范中正确测试用户是否被分配了'company_admin'角色,以防他是与公司关联的第一个用户?


更新 工作解决方案

describe "#check_for_initial_company_admin_role" do
  it "sets the first user created to be the administrator" do
    Factory(:role)
    user = Factory(:user)

    user.roles.count.should be > 0
    user.roles.should include Role.find_by_name("company_admin")
  end
end


Factory.define :user do |f|
  f.email { Factory.next(:email) }
  f.password "secret"
  f.password_confirmation "secret"
  f.association :company
end 

Factory.define :role do |f|
  f.name "company_admin"
end

Factory.define :company do |f|
  f.name "foobar"
  f.vat_id "1234"
end

2 个答案:

答案 0 :(得分:1)

我会这样做:

describe "#check_for_initial_company_admin_role" do
  it "sets the first user created to be the administrator" do
    company = Factory(:company)
    user = Factory(:user)
    company.users << user


    user.roles.count.should > 0
    user.roles.should include Role.find_by_name("company_admin")
  end
end

这里可能不正确的假设是您在测试框架中使用Factory Girl。如果没有,这并没有真正改变这个测试的“肉”......只是你创建公司和用户的第一行。

您也可以选择从公司方面检查用户,但老实说,这完全是一个不同的测试 - 一个测试这些模型之间的关联。

我将采用的方法是,由于这实际上是一个模型测试,您需要创建和更改真实的模型对象,而不是模拟这些对象。如果这是一个控制器测试,我会嘲笑模型并积极地对模型进行存根。

我希望这有助于解决您的问题。如果没有,让我知道我不在哪里,我会再次通过它:)我只有一年的时间进入rspec但我发现一旦我绕过如何测试模型与控制器我已经爱上了它。

答案 1 :(得分:0)

在不改变现有逻辑的情况下,我会在user_spec中测试这个逻辑,如下所示:

describe User do
  let!(:admin_role) { Role.create!(name: 'company_admin') }
  let!(:company) { Company.create! }

  it 'should be added to the default role when created' do
    user = company.users.create!(name: 'Joe', email: 'joe@email.com')

    user.should have(1).roles
    user.roles.first.should == admin_role
  end
end

注意:我会使用像FactoryGirl这样的东西来管理角色和公司对象,以使它们可以重复使用。

您使用角色名称来表示行为并不理想。它可能会导致整个应用程序中出现大量分散的逻辑,您可以通过其名称查找角色并使用if / else或case语句检查名称。我建议使用Rail的单表继承并将所有管理角色逻辑移动到单独的类。它将使模型的逻辑更清晰,并使测试更容易。