2

The RSpec Book を読んでいるうちに、as_null_objectメソッドに出くわしました。なぜそれが必要なのかについて、本が提供する説明を理解できません。

... 最も簡単な方法は、二重出力に、期待するように指示したメッセージのみをリッスンし、他のメッセージを無視するように指示することです。

しかし、サンプル コードが失敗するのはなぜでしょうか? double('output')各例で呼び出すとき、例ごとに新しい double オブジェクトを作成し、単一のメッセージを送信していませんか?

私が望むのは、コード例が失敗する理由とas_null_object、問題にどのように対処するかについて (本よりも) 詳しい説明です。

  it "sends a welcome message" do
    output = double('output')
    game = Game.new(output)
    output.should_receive(:puts).with('Welcome to Codebreaker!')
    game.start
  end

  it "prompts for the first guess" do
    output = double('output')
    game = Game.new(output)
    output.should_receive(:puts).with('Enter guess:')
    game.start
  end

この本は、前のセクションでエラーの理由を説明しようとしていますが、やはり説明がわかりません。

puts最初の例では、 "Welcome to Codebreaker!"を期待するよう double に指示しました。その要件は満たしましたが、「Codebreaker へようこそ!」と期待するように指示しただけです。「推測を入力してください:」については何も知りません。

同様に、2 番目の例の double は「推測を入力してください:」を想定していますが、最初に取得するメッセージは「Codebreaker へようこそ」です。

4

2 に答える 2

2

で double を作成し、output = double('output')それを で新しいゲームに渡すとGame.new(output)、その double は codebreaker ゲーム コードで渡されたすべてのメッセージを受け取ります。含めていませんが、startメソッドには次のコードがあります。

module Codebreaker
  class Game
    ...
      def start
        @output.puts 'Welcome to Codebreaker!'
        @output.puts 'Enter guess:'
      end
  end
end

ここで、 double が'sメソッドoutputのインスタンス変数@outputに割り当てられていることを思い出してください。そのため、各仕様では、最初に「Codebreaker へようこそ!」、次に「推測を入力してください:」という 2 つのメッセージで呼び出されます。gameinitialize

がないas_null_objectと、outputdouble は期待しているもの以外を受け取ると失敗します。つまり、最初の仕様で 'Welcome to Codebreaker!' 以外のものを受け取ります。2 番目の仕様では、「推測を入力してください:」以外のもの。二重に使用as_null_objectすることで、座って待って、期待しているもの以外は無視するように指示します。これにより、上記の問題が回避されます。

それが役立つことを願っています。

于 2012-10-03T22:44:08.223 に答える
1

説明が明確ではないことに同意します。これが私が理解していることです。おそらく、塩山の答えと組み合わせると、このクリックが発生します。

仕様を作成しているとき、出力に予期されるフレーズが含まれると言っているのですが、予期されたフレーズのみが含まれているわけではありません。したがって、次のように、すべての期待値を 1 つの例にまとめることで、エラーを回避したとしましょう。

   it "gets expected output" do
     output = double('output')
     game = Game.new(output)
     output.should_receive(:puts).with('Welcome to Codebreaker!')
     output.should_receive(:puts).with('Enter guess:')
     game.start
   end

これは通過します。問題は、後で「Hi Joe!」と言ってゲームを開始することにした場合、失敗することです。次に、実際にはすでに仕様を満たしているのに、戻って仕様を修正する必要があります。出力が予期しない入力に応答して動作しないメカニズムが必要です。そうすれば、予期せぬ事態が発生したときに失敗することなく、期待される出力の具体例を得ることができます。これは非常に基本的なプログラミングと単体テストのアサーションのように思えますが、RSpec ではこの方法で実装されているため、あなたや私にはわかりにくいと思われるかもしれません。は行っていますが、null オブジェクト パターン ( http://en.wikipedia.org/wiki/Null_Object_pattern ) の実装です。

于 2014-05-16T15:24:12.103 に答える