いくつかの定数を宣言したPerlモジュールがあります。
use constant BASE_PATH => "/data/monitor/";
ライブ操作では定数は変更されませんが、単体テストで変更できるようにしたいと思います。たとえば、に設定し~/project/testdata/
ます。グローバルな可変変数を使用せずにこれを行う方法はありますか?
私はおそらくで使用できTest::MockObject
ますconstant
か?
いくつかの定数を宣言したPerlモジュールがあります。
use constant BASE_PATH => "/data/monitor/";
ライブ操作では定数は変更されませんが、単体テストで変更できるようにしたいと思います。たとえば、に設定し~/project/testdata/
ます。グローバルな可変変数を使用せずにこれを行う方法はありますか?
私はおそらくで使用できTest::MockObject
ますconstant
か?
定数を使用する場合、次のような動作をする定数関数として実装されます。
use subs 'BASE_PATH';
sub BASE_PATH () {"/data/monitor/"}
プログラムでの BASE_PATH の使用はすべてインライン化されているため、変更できません。
同様のことを実現するには、subs プラグマを手動で使用して (BASE_PATH を組み込み関数として動作させるため)、BASE_PATH を標準関数として宣言します。
use subs 'BASE_PATH';
sub BASE_PATH {"/data/monitor/"}
print "BASE_PATH is ".BASE_PATH."\n";
*BASE_PATH = sub {"/new/path"};
print "BASE_PATH is ".BASE_PATH."\n";
なぜあなたがこれをやりたいのか、私にはよくわかりません。
テストによって、設計の柔軟性の欠如が明らかになることがよくあります。これはそれらの時間の 1 つです。その定数は定数であってはなりません。
パフォーマンス上の理由でそれを行っているのであれば、私はそれが何の違いももたらさないことを確信しています。
パッケージ My::Class; 定数 BASE_PATH を使用 => "/a/real/value/"; # ..その他のコードはこちら.. 1;
ユニットテストで:
My::Class を使用します。 *{My::Class::BASE_PATH} = sub { "/a/fake/value" }; # ここでテストを行います...
どうやら、テストがそれを変更する前に、BASE_PATHの定義が使用/別のサブルーチンにコンパイルされた場合(
*BASE_PATH = sub { ... }
または他のもの) 解決策がありません (元のモジュールが定数として BASE_PATH を使用していたとき、他のコードで使用されたときにインライン化された INLINE 関数を実際に定義したため)