0

ObjectSpace 関連の 2 つのメソッドを持つ 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=[]>]

ご覧のとおり、これにより、配列内のオブジェクトが 2 倍になりますが、コード自体は正常に動作します。では、なぜ私のテストが失敗するのでしょうか?

4

3 に答える 3

2

以前にProject存在していた がオブジェクトとしてまだ存在するためです。

これは、オブジェクトがまだ にあることを意味し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. テスト対象のクラスとテスト自体のリファクタリング。具体的には、関心のある Project オブジェクトへの参照を保持するために ObjectSpace に依存するのではなく、何らかの集約パターンを使用します。

ここではさまざまなものを組み合わせることができますが、テストを修正することは実際には問題の一部にすぎません。基礎となるアプリケーション ロジックは、リファクタリングが必要なようです。

不合格のテストは、手術が必要なクラスを強調するという点で優れています。テストを修正するだけではありません。テスト中のクラスについて仕様が伝えようとしていることに耳を傾けてください。

于 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

project.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 に答える