4

Flexmock モッキング フレームワークを使用して、Rspec2 でテストを作成しています。メソッドの 1 つが結果をキャッシュすることを期待しており、これをモックで検証したいと考えています。

describe SomeClass do
  before do
    @mock = flexmock()
  end

  after do
    @mock.flexmock_verify()
  end

  it "method caches results"
    c = SomeClass.new(@mock)
    c.method
    @mock.should_receive(:expensive_method).never
    c.method.should == ['A']
  end
end

:expensive_method決して呼び出されないようにしたい場合、これは適切に機能します。:methodただし、渡された (モック) クラスで何も呼び出さずにクラスが実行できることを期待しています。これを表現する方法はありますか?

背景:私の場合、注入されたクラスはコストのかかる操作を実行するため、同等のクエリに対して結果をキャッシュする必要があります。

更新
これまでの提案に感謝します。おそらく、間違ったことを想定しているだけか、私が望むものが意味をなさないかもしれません。キャッシングを実装する方法は、クラス変数を保持し、SomeClassそれに追加することです:method

def SomeClass
  @@cache_map = {}

  def method
    # extract key
    return @@cache_map[key] if @@cache_map.has_key?(key)
    # call :expensive_method to get result
    @@cache_map[key] = result
    return result
  end
end

ここで、正しいキャッシングをテストするために、:extensive_method少なくとも 1 回呼び出してキャッシュをロードする必要があります。私はDavid Chelimskyの解決策が好きですが、それは私の当初の意図に答えていません。つまりSomeClass.method、注入されたクラスへの最初の呼び出しの後、二度と呼び出されないことをテストします(どちら:expensive_methodも他にもありません)。

4

2 に答える 2

9

キャッシングを指定する従来の方法は、まったく@mock.should_receive(:expensive_method).once呼び出す前に言ってから、それを呼び出すメソッドを 2 回呼び出すことです。method

また、これには 2 つの例を使用したいと思います。1 つはデータの使用方法を指定するもので、もう 1 つはデータを 1 回だけ取得することを指定するものです。

describe Client do
  let(:service) { flexmock() }
  let(:client)  { Client.new(service) }

  it "uses data retrieved from service" do
    service.stub(:expensive_method).and_return('some data')
    client.method.should eq('some data')
  end

  it "only retrieves the data once" do
    service.should_receive(:expensive_method).once
    client.method
    client.method
  end
end

また、自動的に行われるため、 を呼び出す必要はありませんflexmock_verify

于 2011-06-16T12:28:24.860 に答える
1

確かに、モックされたオブジェクトに期待を設定しないと、これが達成されますモックを呼び出すと、予期しない呼び出しエラーが発生します (Flexmock を使用したことはありませんが、使用した他のすべてのモック フレームワークはこのように機能します)。

残念ながら、テストでこれを明示する方法は実際にはありません。それを示すためにテスト名を変更するかもしれません。「メソッドは、モックされたオブジェクトを呼び出さずにキャッシュされた結果を使用する」のようなものかもしれません。

于 2011-06-16T09:32:23.780 に答える