課題解決Tips

【C++】 gMockのEXPECT_CALLでエラーが出た時

salmoncode
記事内に商品プロモーションを含む場合があります。

こんにちは。エンジニアのサーモンです。

今回はgMockでハマったので、備忘録として記事を書きます。

gMockとはGoogle製のモックフレームワークで、同じくGoogle製のC++テストツールであるGoogleTestと合わせて使います。

gMockを使うことで、テスト対象が依存先の関数を呼び出したかチェックすることができます。
また、モックに特定の値を返させることで、関数の返り値によるテスト対象の振る舞いをテストすることもできます。

gMockで関数の呼び出しを確認する際にはEXPECT_CALLを記述するのですが、ポインタが絡むケースでハマりました。

以下が今回のケースの例です。

コードを簡単に説明すると、
AppleTreeというクラスがあり、そのインスタンスメソッドであるGetLife()をテストしています。
AppleTreeはAppleに依存しており、GetAppleLifeでAppleのGetLifeを呼び出します。
そこで、AppleをモックしてGetLifeの呼び出しをチェックしようというケースですね。

AppleTreeはAppleをunique_ptrで受け取ります。そのためappleをstd::moveするのですが、実装コードのミスでメンバ変数に保存されません。

そのため、appleが破棄されてしまい、EXPECT_CALLの実行時に不正なポインタになってしまいます。
そのため、このテストを実行するとクラッシュしてしまいます。

実装コードの不具合はメンバ変数の初期化忘れのため、プログラムの実行時には未定義挙動になります。このようなケースもテストで分かるのはありがたいですね。
今回は以下のように修正することで解消されました。

ただ、今回はクラッシュ時のダンプしか得られなかったので調べるのに時間がかかってしまいました。

デバッグしてもメソッドがUntypedFunctionMockerBaseになっているくらいしか分からず、辿っていくとmockObjをnullと比較している箇所があったので気づけた次第です。

参考になりましたら幸いです。

スポンサーリンク
書いた人
サーモン
サーモン
著者(ソフトウェアエンジニア)
こんにちは、ソフトウェアエンジニアのサーモンです。 情報系大学院を卒業後、都内IT企業に従事しています。プログラミング歴は10年以上になります。
記事URLをコピーしました