1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PerlのTest Tips メソッド内で面倒な関数が呼ばれているから、回避したい場合

Posted at

Perlのテストを作っているとき、あるメソッドで呼ばれている関数が邪魔なので、任意の値を返すようなモックにしたい場合。

邪魔な関数 = 例えば、その関数はネットワークアクスが必要とか、DBアクセスして、特定のデータセットが必要とか。

テスト対象モジュール
package TestTargetXXX;

use Some::Module qw(getIDfromDB);

sub sample_func {
    my $self = shift;
    my %param = @_;

    my $id = &getIDfromDB($param{key});
    # (略)
    return $key_code;
}
テストスクリプト(の一部)
subtest "sample_func test." => sub {
    my $obj = TestTargetXXX->new();

    %param = (key => 'XXX');
    $rtn = $obj->sampel_func(\%param);
    is $rtn, 'YYY';
};

ここで&getIDfromDB()を動かすには、DBの準備が必要で面倒。なので、モック化する。(もちろん、この関数は別途、テスト済み)

テストスクリプト(新)
subtest "sample_func test." => sub {
    my $test_id = undef;
    no warnings 'redefine';
    local *TestTarget::getIDfromDB = sub {return $test_id};
    use warnings 'redefine';

    my $obj = TestTargetXXX->new();

    %param = (key => 'XXX');
    $test_id = 'ZZZ';
    $rtn = $obj->sampel_func(\%param);
    is $rtn, 'YYY';
};

要点として、

  • *TestTarget::getIDfromDB = sub {...}で強制的に関数を置き換え
  • 置き換えが全体に影響しないようlocalで宣言
  • この置き換え方法は、警告が出るのでno wanings 'redefine';で抑制(use warnings;使ってないなら不要)

もう少し「強制的な置き換え」について説明すると、

  • getIDfromDB()は、TestTargetモジュール内でexportされている。
  • そのため、getIDfromDB()はSome::Moduleのものだが、TestTargetの関数ともいえる。
  • つまり、&TestTarget::getIDfromDB()ともいえる。
  • なので、*TestTarget::getIDfromDB = sub {}で強制的に上書き出来る。

最後に
CPANにありそうですが、Perl単体でなら上記の方法で対処可能。あと、モックの使いすぎ注意。別途、結合テストはきちんとする。そもそも、こんなテストしにくい実装はしない。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?