使用rspec进行模型测试

时间:2010-12-24 07:15:51

标签: rspec

我有一段我想测试的代码:

class User < ActiveRecord::Base

 has_many :servers, :dependent=> :destroy

end

请举例说明测试关联代码的RSpec代码。

6 个答案:

答案 0 :(得分:8)

对我来说,这种变体效果很好:

describe User do
  it { should have_many(:servers).dependent(:destroy) }
end

答案 1 :(得分:4)

在回答您当前的问题时,您现在可能会对此有所帮助,您真正需要的是了解测试。

您想为已经存在的代码编写测试。使用TDD方法,您将做相反的事情:首先编写测试,然后编写使测试通过的代码。

我建议您通过实用程序员购买RSpec Book。它会非常清楚地向您解释您应该做什么以及如何做。非常好的书,值得每一分钱。

另一个答案说你应该使用Shoulda。虽然这是一个很好的做法,但请先尝试自己做。一旦你理解了你应该做什么,那么你可以使用像Shoulda这样的抽象。

另一个答案使用工厂。虽然这是一个很好的做法,但我建议您首先使用RSpec内置工具,如Mock对象和存根方法。一旦了解了这两者的运作方式,就可以使用像Factories这样的抽象。顺便说一句,制作更简单。

答案 2 :(得分:1)

我在这里使用工厂女孩:

it "should be destroyed when user is destroyed" do
  @user.servers << @server
  @user.destroy
  Server.all.should_not include(@server)
end

但您也可以在测试中创建一个新用户:

it "should be destroyed when user is destroyed" do
  user = User.create(:name => "Julia")
  user.servers << Server.create(:server_name => "Julias server")
  user.destroy
  Server.all.should_not include("Julias server")
end

答案 3 :(得分:1)

我提出了两种方法:快速和肮脏,以及D.R.Y和清洁:)

快速而肮脏:

context "when testing dependent: destroy" do
  before do
    @user = User.create
    @servers = [Server.create]
    @user.servers = @servers
  end 

  it "should destroy all of the associated servers" do
    @servers.each{|s| Server.exists?(s.id).should be_false}
  end
end

要以干燥且可重复使用的方式执行此操作,仅依赖于rspec本身,您需要为HasMany定制匹配器。高级规范将如下所示:

Subject { User.new }
it { should have_many :tasks, dependent: :destroy }

然后匹配器将如下所示:

RSpec::Matchers.define :have_many do |_association, opts|
  if opts and opts[:dependent]

    match do |model|
      associations(model, :has_many, opts).any? { |a| a == _association }
    end

    failure_message_for_should do |model|
      error(
        :expected => [ "%s to have many %s and to have dependent => :destroy %s", model, _association, opts[:dependent] ],
        :actual   => [ "%s has many %s ", model, associations(model, :has_many) ]
      )
    end

  else

    match do |model|
      associations(model, :has_many).any? { |a| a == _association }
    end

    failure_message_for_should do |model|
      error(
        :expected => [ "%s to have many %s", model, _association ],
        :actual   => [ "%s has many %s", model, associations(model, :has_many) ]
      )
    end

  end
end

您将需要此rspec辅助模块:http://pastie.org/6356719

我喜欢第一种方法,即使它很脏,因为它进入数据库并使用完整的rails堆栈...但有人认为这太过耦合了。第二种方法更干燥,但需要一个帮助,只是反映在关联本身,可能不会涵盖可能搞砸删除相关对象的其他问题......

答案 4 :(得分:0)

在RSpec中测试关联的一种方法是使用shoulda。 Shoulda是一组帮助者,可以快速编写常见的重复测试,同时可以理解。要测试您的模型,请确保已安装并需要shoulda gem。然后,您可以使用以下内容测试您的关联:

describe User do
  it {should have_many :servers, :dependent => :destroy}
end

答案 5 :(得分:0)

对于简单的规范示例/代,我建议使用gem regressor:

https://github.com/ndea/regressor

此gem将根据关系/验证/数据库/回调为您的模型生成一些简单的规范,您可以在其中定位未来的规范。