Perl で狭義のモックを作る Test::Double 19:51

Posted at 2010/07/27 19:51, Modified at 2010/07/27 20:54

Ruby の Mocha や Python の Mox は「特定の順序で特定のメソッドが特定の引数と呼ばれるか」というところにフォーカスしているように思う。

そもそも「モック」をそういう狭義の意味でつかう一派もいるらしい。Wikipedia の Mock object にはこうある。

Mock objects in this sense do a little more: their method implementations contain assertions of their own. This means that a true mock, in this sense, will examine the context of each call— perhaps checking the order in which its methods are called, perhaps performing tests on the data passed into the method calls as arguments.

その数個前の段落からリンクされている『レガシーコード改善ガイド』にはこうあった。

モックオブジェクトは、想定されるメソッド呼び出しを事前に設定し、メソッド呼び出し後に検証を指示することで、その呼び出しが実際に行われたかどうかを確認できる仕組みです。

さて、Perl の Test::MockObject にも next_call, call_pos といった「n 番目に呼ばれたメソッドはなにか、どうよばれたか」というのを検査する手段はある。でも、個人的には Mocha や Mox のようなインターフェースが好きなので Test::Double というのを書いてみた。

Test::Double

たとえば write_file メソッドが「引数に渡された $io に対して $io->print('hello') を呼び出す」みたいなことをテストしたいとすると

my $double = Test::Double->new;
$double->expects('print')->with('hello');
  
$double->verify_ok(
    sub { my $io = shift; write_file($io); }
);

こんな感じ。メソッド名は Mocha 風、verify を明示的に呼ぶのは Mox 風という感じで、ベタな移植ではない。

expects は AUTOLOAD をハックしてメソッド呼び出し風に書けるほうが、と一瞬思ったけど、そうすると "expects" というメソッドがあるクラスの振りをしづらいので、明示的にメソッドを呼ぶ形にした。あと Mox の Comparators をみて、メソッド風インターフェースの限界を感じたのもある。Perl でこういうの作るよりは Test::More::like とか使えるほうがうれしいと思う。

もうちょっと使ってみて、インターフェースとか固まったら CPAN にあげる予定。意見募集中です。

3 comments
kzys : Test::Mock ないし Test::Expectation があった... (2010/07/27 21:07)
mrmt : s/excepts/expects/ (2010/09/09 01:12)
kzys : 直しました。ありがとうございます。 (2010/09/12 18:10)
riddle for guest comment authorization:
Where is the capital city of Japan? ...

blog.8-p.info加藤和良 の個人的なブログで、プログラミングのはなしが多めです。