2

私のコードには、次の不自然な例のようなコードがあります。

class Excel
  def self.do_tasks
    with_excel do |excel|
      delete_old_exports
      export_images(excel)
      export_documents(excel)
    end
  end

  def with_excel
    excel = WIN32OLE.connect('Excel.Application')
    begin
      yield excel
    ensure
      excel.close()
    end
  end
end

ここで、「do_tasks」メソッドのテストを書きたいと思います。そこでは、メソッド呼び出しの期待値を設定し、それらの期待値が満たされるかどうかを確認します。

次のアプローチを試しました(shoulda-contextとtest-unitを使用)。ただし、最後の 3 つのモックでは、期待は失敗します (モックは呼び出されません)。

class ExcelTest < ActiveSupport::TestCase  
  should "call the expected methods" do  
    mock.proxy(Excel).with_excel
    mock(Excel).delete_old_exports
    mock(Excel).export_images.with_any_args
    mock(Excel).export_documents.with_any_args

    Excel.do_tasks
  end
end

この種のコードをテストする方法についての指針は大歓迎です!

4

1 に答える 1

1

古い質問ですが、私は rr を使用して同様のコードでいくつかの作業を行っていたので、回答を投げたいと思いました。

次のテストは、(RR と TestUnit を使用して) 要求したことを実行します。

describe Excel do
  describe '.do_tasks' do
    let(:excel_ole) { mock!.close.subject }

    before do
      stub(WIN32OLE).connect('Excel.Application') { excel_ole }
      mock(Excel).delete_old_exports
      mock(Excel).export_images(excel_ole)
      mock(Excel).export_documents(excel_ole)
    end

    it 'calls the expected methods' do
      Excel.do_tasks
      assert_received(Excel) { |subject| subject.delete_old_exports }
    end
  end
end

RR の「スパイ」ダブルを使用します - https://github.com/rr/rr#spiesを参照してください

ただし、提供されたサンプル コードの場合、テストするメソッドがブロック内にあるという事実は実装の詳細であり、暗黙的にテストする必要はありません (これは脆弱なテストにつながる可能性があります)。上記のテストは、with_excel メソッドがモックされていないことを示しています (ちなみに、コードが機能するには、これを self.with_excel として定義する必要があります)。WIN32OLE の初期化とティアダウンが .do_tasks メソッドでインラインで行われ、テストに合格するように、実装をリファクタリングすることができます。

別の注意として、これは不自然な例の副作用かもしれませんが、一般的に非公開メソッドをテストするのは悪い考えです。メソッド delete_old_exports、export_images、および export_documents は、共同作業者に除外する必要があるようです。

于 2013-04-17T09:04:58.110 に答える