Test::MockObject失敗談
Test::MockObjectを使っていたんですが、ちょっとこれでハマってました。
テスト時に、何らかの理由でモジュールのメソッドを偽装する際は、Test::MockObject->fake_moduleを使用します。
たとえば、テストで使用するモジュールが実装されてなく、それでも通るようにしたい場合や、実装したモジュールの中で正常にメソッドが呼ばれているか、といった場合に使用されます。今回ハマったのは後者です、ほんとしょうもない理由だったんですが。
my $mock = Test::MockObject; $mock->fake_module( 'My::Object', any_method => sub { ok(1, 'any_method got called successfully'); } );
このようにすると、My::Objectのany_methodが呼び出された際にokを返し、テストが成功します。any_method got called successfullyとテストを問題なく通過した文言が出力されるはずです。
しかし、このany_methodにはDBIx::Skinny::Rowオブジェクトの返り値があります。
この場合、Test::MockObjectで偽装したメソッドには返り値を設定していないので、その返り値を参照した時点でコケてしまいます。
このMy::Object::any_methodは本命のテストを行うモジュールの更に1つ深くで呼ばれており、それが呼ばれていることを確認するためにTest::MockObjectを使用していました。返り値を変えた事を忘れてて・・・って感じです。
my $mock = Test::MockObject; $mock->fake_module( 'My::Object', any_method => sub { ok(1, 'any_method got called successfully'); return Hoge::Model->hash_to_row( 'hoge_tbl', { id => 1, column => "hogehoge", } ); } );
このようにDBIx::Skinny::Rowオブジェクトをhash_to_rowメソッドにより、ハッシュから作って返す事によって無事解決。
DBIx::Skinnyやっぱり便利!と思うと同時にテストはしっかり書こうとしみじみと思うのでした。
Test::MockObjectも初めて使ってみましたが、これは色々楽できますねー