Tech Blog

グローバルな家族アプリFammを運営するTimers inc (タイマーズ) の公式Tech Blogです。弊社のエンジニアリングを支える記事を随時公開。エンジニア絶賛採用中!→ https://timers-inc.com/engineering

1つのメソッドの中で同じ例外クラスがスローされている場合にテストする方法

サーバーサイドエンジニアの鈴木です。

PHPUnit では期待する例外が発生することをテストするために、@expectedException アノテーションが用意されています。このアノテーションに例外クラス名を指定することで、そのテストが実行されたときに指定した例外クラスのインスタンスがスローされるかどうかテストをすることができます。

しかしながら、 同じ例外クラス (例えば、Exception クラス等)のインスタンスがそのままスローされているメソッドが複数含まれている場合、@expectedException アノテーションだけではどの例外が発生するのか識別することができません。

具体例を用いてご説明します。

例えば、下記のような 1 つのメソッドの中に 2 箇所で同じ例外クラスの例外が発生させるメソッドがあったとします。この場合、Exception クラスのインスタンスがスローされることはテストすることができますが、どちらの例外が発生したのか判別することができません。

<?php

class Sample {
    public function helloWorld($a, $b) {
        if (!$a) {
            throw new Exception('$a is invalid');
        }
        if (!$b) {
            throw new Exception('$b is invalid');
        }
        return 'Hello World';
    }
}

その場合の解決方法の 1 つとして、@expectedExceptionMessage @expectedExceptionMessageRegExp @expectedExceptionCode といったアノテーションを使用するという方法があります。

これらのアノテーションの動作は下記の通りです。

  • @expectedExceptionMessage : 期待する例外メッセージをテストする
  • @expectedExceptionMessageRegExp : 期待する例外メッセージを正規表現を使用してテストする
  • @expectedExceptionCode : 期待する例外コードをテストする

@expectedExceptionMessage アノテーションを使用して 2 つの例外をテストする場合は下記のようなコードになります。

<?php

require 'Sample.php';

class SampleTest extends PHPUnit_Framework_TestCase {

    /** 
     * @expectedException Exception
     * @expectedExceptionMessage $a is invalid
     */
    public function testHelloWorldThrowsExpectedExceptionMessageWhenAIsNull() {
        $sample = new Sample();
        $sample->helloWorld(null, 'test');
    }   

    /** 
     * @expectedException Exception
     * @expectedExceptionMessage $b is invalid
     */
    public function testHelloWorldThrowsExpectedExceptionMessageWhenBIsNull() {
        $sample = new Sample();
        $sample->helloWorld('test', null);
    }   
}

@expectedExceptionCode アノテーションを使う場合は、Exception クラスのコンストラクタの第 2 引数に任意の例外コードを渡すように修正することが必要になりますが、それ以外は @expectedExceptionMessage アノテーションと同じように使うことができます。

この方法では既存のメソッドの挙動を変えずに(またはほとんど変えることなく)例外が発生するケースをテストでカバーすることができますので、そういった場面に出くわしたらぜひお試しください。

公式ドキュメント

積極採用中!!

子育て家族アプリFamm、カップル専用アプリPairyを運営するTimers inc. では、現在エンジニアを積極採用中! 急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください! 採用HP : http://timers-inc.com/engineerings

Timersでは各職種を積極採用中!

急成長スタートアップで、最高のものづくりをしよう。

募集の詳細をみる