0

我有一个带有两个与 ObjectSpace 相关的方法的 Project 类:

def self.all
  ObjectSpace.each_object(self).to_a
end

def self.count
  ObjectSpace.each_object(self).count
end

此规范失败:

it "can print all projects" do
  Project.all.should eq([@project1, @project2])
end

出现以下错误:

Failure/Error: Project.all.should eq([@project1, @project2])

       expected: [#<Project:0x007fd76a815508 @name="Building house", @tasks=[]>, #<Project:0x007fd76a815198 @name="Getting a loan from the Bank", @tasks=[]>]
            got: [#<Project:0x007fd7688336b8 @name="Building house", @tasks=[]>, #<Project:0x007fd7688dae40 @name="Building house", @tasks=[]>, #<Project:0x007fd768af4de8 @name="Getting a loan from the Bank", @tasks=[]>, #<Project:0x007fd768af5090 @name="Building house", @tasks=[]>, #<Project:0x007fd76a815198 @name="Getting a loan from the Bank", @tasks=[]>, #<Project:0x007fd76a815508 @name="Building house", @tasks=[]>]

如您所见,这使我的数组中的对象翻了一番,但代码本身工作正常。那么为什么我的测试失败了?

4

3 回答 3

2

因为先前存在Project的 s 仍然作为对象存在。

这意味着它们仍会在 中找到ObjectSpace,并且您将拥有比预期更多的对象。

于 2013-01-14T15:07:15.540 回答
1

ObjectSpace 可能包含坚果的痕迹

嗯,不是真的。但是 ObjectSpace 通常包含属于其他范围的对象,已标记为垃圾回收但尚未删除的对象,或者(特别是在 RSpec 测试的情况下)来自 before 块的多次调用的对象副本。

Ruby 2.0 可能有所不同,但早期的 MRI 解释器不保证垃圾回收,因此即使手动运行GC.start也不能​​真正指望 ObjectSpace 的内容对相等性测试有效。

重构你的代码

与其在规范中寻找平等,不如考虑:

  1. 寻找包含在Array#include 中?
  2. 在 ObjectSpace 中查找特定的对象 ID。
  3. 重构被测类以及测试本身。具体来说,使用某种聚合模式而不是依赖 ObjectSpace 来保存对您关心的 Project 对象的引用。

你可以在这里混搭,但修复你的测试实际上只是问题的一部分。底层应用程序逻辑似乎需要重构。

不及格的测试很好,因为它突出了需要手术的课程。不要只是修复测试;听听规范试图告诉你关于被测类的内容。

于 2013-01-14T15:45:26.173 回答
1

project_spec.rb

describe Project do

 let(:p1) { Project.new }
 let(:p2) { Project.new }

 describe ".all" do

  it "should keep track of all pr" do
   Project.all.should == [p1, p2]  
  end

 end

 describe ".count" do

  it "should count all the projects" do
   Project.count.should == 2
  end

 end

end

项目.rb

class Project

  @@all_projects = []

  def initialize(options=nil)
    @@all_projects << self
  end

  def self.all
    @@all_projects
  end

  def self.count
    @@all_projects.count
  end

end


Finished in 0.00079 seconds
2 examples, 0 failures

我会留给你来制定可能对你的项目来说具体和复杂的其他细节。希望这对你有用。

于 2013-01-14T16:37:04.200 回答