3

私が理解しているように、単体テストでは、環境の変更の影響を受けないように、メソッドを依存関係から分離する必要があります。

それでも、すべての依存関係をスタブ化すると、動作ではなく実装をテストしているように感じます。

言い換えれば、依存関係を分離することで、テストを実装の詳細に結合しています。したがって、コードのリファクタリングは、動作 (望ましい結果) が変わらなくても、テストの失敗を引き起こします。

たとえば、これは単純な (Ruby) メソッドです。

  def send_request
    update_attributes(response.page_params) if active?
  end

そして、これらは、この 1 行のコードに対する私の 2 つの独立したテストです。

  let(:page) { Page.new }

  describe '#send_request' do
    context 'when a page is active' do
      it 'updates page with the response parameters' do
        page.active = true
        response = double('response')
        page_params = double('page_params')
        response.stub(:page_params).and_return(page_params)
        page.stub(:response).and_return(response)
        page.stub(:update_attributes).and_return(nil)
        page.should_receive(:update_attributes).with(page_params)
        page.send_request
      end
    end
    context 'when a page is inactive' do
      it 'does NOT send a request' do
        page.active = false
        page.should_not_receive(:response)
        page.send_request
      end
    end
  end

テストはパスしていますが、深刻な問題がいくつか見られます。

  • 後で update_attributes() 以外の方法を使用して変更をデータベースに保持することにした場合、データは期待どおりに保存されますが、テストは失敗します。
  • response.page_params の実装が変更された場合、ソフトウェアは本番環境で失敗しますが、テストは引き続き合格します

私は何か間違ったことをしているに違いない。

単体テストを書く正しい方法は何ですか?

4

1 に答える 1

4

AlistairIsrael が言ったように、ここで完全に的外れだとは思いません。

より簡潔にするためにできる最適化がいくつかあります。優れたテストは、コードから何を期待しているかを明確に示す必要があります。

let(:page) { Page.new }

describe '#send_request' do
  context 'when a page is active' do
    it 'updates page with the response parameters' do
      page.active = true
      response = double('response',
        :page_params => page_params = mock('page_params')
      )

      # not needed as .should_receive creates a nil stub by default.
      # page.stub(:update_attributes).and_return(nil)
      page.should_receive(:update_attributes).with(page_params)
      page.send_request
    end
  end
  context 'when a page is inactive' do
    it 'does NOT send a request' do
      page.active = false

      subject.should_not_receive(:update_attributes)
      page.send_request
    end
  end
end

上記のいくつかの変更から、rspec の double ヘルパーが非常に強力であることがわかります。複雑なオブジェクトを作成し、いくつかの割り当てを使用して、チェーン内の最後に評価されたメソッドにアクセスできます。

私は負のケースを仮定しましたが、あなたはそのアイデアを理解する必要があります. のメソッド呼び出しのテストupdate_attributesはおそらく簡単で明確page_paramsです。条件を満たしていません。

HTH

于 2012-12-04T08:45:38.287 に答える