Rspec:如何创建模拟关联

时间:2015-12-19 09:37:30

标签: ruby-on-rails rspec

我有以下课程:

class Company < ActiveRecord::Base

  validates :name,   :presence => true

  has_many :employees, :dependent => :destroy

end


class Employee < ActiveRecord::Base

  validates :first_name,     :presence => true
  validates :last_name,      :presence => true
  validates :company,        :presence => true   

  belongs_to :company

end

我正在为Employee课程编写测试,因此我正在尝试为double创建CompanyEmployee将使用let(:company) { double(Company) } let(:employee) { Employee.new(:first_name => 'Tom', :last_name => 'Smith', :company => company) } context 'valid Employee' do it 'will pass validation' do expect(employee).to be_valid end it 'will have no error message' do expect(employee.errors.count).to eq(0) end it 'will save employee to database' do expect{employee.save}.to change{Employee.count}.from(0).to(1) end end

以下是我的Rspec的片段

ActiveRecord::AssociationTypeMismatch:
   Company(#70364315335080) expected, got RSpec::Mocks::Double(#70364252187580)

我收到了所有3次测试的错误消息

double

我认为我尝试创建double of Company的方式是错误的。您能否指导我如何创建Employee FactoryGirl作为他们的关联。

我没有使用<a data-url="htts://xyz@..." class="mybuttons" data-type="facebook">

非常感谢。

2 个答案:

答案 0 :(得分:1)

实际上并没有很好的方法,但我不确定你是否需要这样做。

你的前两个测试基本上是测试相同的东西(因为如果employee有效,employee.errors.count将为0,反之亦然),而你的第三个测试是测试框架/ ActiveRecord,而不是你的任何代码。

正如其他答案所提到的,Rails在以这种方式验证时需要相同的类,所以在某些时候你必须坚持company。但是,您可以在一次测试中完成此操作,并在所有其他测试中获得所需的速度。像这样:

let(:company) { Company.new }
let(:employee) { Employee.new(:first_name => 'Tom', :last_name => 'Smith', :company => company) }

context 'valid Employee' do
  it 'has valid first name' do
    employee.valid?
    expect(employee.errors.keys).not_to include :first_name
  end

  it 'has valid last name' do
    employee.valid?
    expect(employee.errors.keys).not_to include :last_name
  end

  it 'has valid company' do
    company.save!
    employee.valid?
    expect(employee.errors.keys).not_to include :company
  end
end

如果您真的想继续进行第三次测试,可以在company.save!区块中加入it,或者禁用验证(但是,您在那时甚至还在测试什么?) :

it 'will save employee to database' do
  expect{employee.save!(validate: false)}.to change{Employee.count}.from(0).to(1)
end

答案 1 :(得分:0)

SO上已经有类似的问题(Rspec Mocking: ActiveRecord::AssociationTypeMismatch)。我认为你无法摆脱使用真正的AR对象,因为似乎Rails检查关联对象的确切类,而double是一些完全不同的类的实例。也许你可以通过一些内部Rails的方法来跳过那个检查,但我认为这是一个开销。