4

G'Day、

次のようなステートメントを使用する関数を単体テストしようとしています。

unless($this->_doc_type eq ref($this->_doc_instance)) {
    # Do something
} 

オブジェクトをどのようにモックしても、ref()をだますことはできません。これをどのようにテストすればよいですか?

  • ?を呼び出すプライベートref()関数がありますCORE::ref()
  • CORE::ref私のユニットテストでオーバーライドしてみてください?
  • ???
4

1 に答える 1

3

古き良き時代には、次の形式のコードがありました

switch (item->type) {
  case FOO:
    do_foo(item);
    break;

  case BAR:
    do_bar(item);
    break;

  default:
    handle_unknown_type(item->type, __FILE__, __LINE__);
    break;
}

アイテムのタイプを明示的に検査してから別の機能に分岐するこのパターンは、システムのソース全体で何度も繰り返されました。

BAZミックスに新しいタイプを追加するときが来たとき、それは戻って、すべてのswitch, if/elseチェーン、またはitem->type.

これは大きな苦痛でした。

オブジェクト指向言語はこのパターンを吸収するので、プログラマーはあちこちに再実装する必要がなく、この低レベルの配管に精神的リソースを浪費する必要もありません。オブジェクト指向とされているコードが古き良き時代を懐かしむとき、

unless ($this->_doc_type eq ref($this->_doc_instance)) { ... }

強烈なコード臭です。

私の最初の提案は、製品コードを再設計することです。条件内で何が起こるか? そのコードの意図は何ですか?

のモックを使用していると思います_doc_instance。コードをリファクタリングする前にテストのサポートを受けるために、 から返された値を変更する方法を調べます_doc_type。これも単純な getter ではないと思います。コンテキストについて他に何も知らない場合、1 つのアプローチは、テスト サブクラスを作成することです。

テストしているクラスがMy::Container. この特定のテスト用に偽のドキュメント (実際のドキュメントの表面的な外観しか持たないドキュメント) で問題を解決できる場合は、次の行に沿ってコードを記述します。

package Test::My::Container_Canned_Type;

use base 'My::Container';

sub _doc_type { "Test::Fake::Document" }

1;

そして、テストで、次のように使用します

my $doc = bless {} => "Test::Fake::Document";
my $c   = Test::My::Container_Canned_Type->new($doc, ...);

あなたのコードの構造について私が間違っていると推測した場合は、より役立つ提案を提供できるように、より多くのコンテキストを提供してください!

この困難な状況に陥ったことは、最初にテストを作成することが役立つ理由の良い教訓です。設計上、頭を悩ませたり、奇妙な実装をテストする方法を考えたりするケースを排除します。

概要

  • いいえ、動作を変更しようとしないでくださいref
  • 可能な限り、ref本番コードでの使用を排除してください。
于 2011-06-15T13:21:21.947 に答える