PHPUnitでassert()がコケることをテストする


やりたいこと

PHP7.1PHPUnit 7.2

class Foo {
  public static function bar(string $a){
    assert($a === "po");
    echo $a;
  }
}

class FooTest extends TestCase{
  /**
   * @test
   */
  public function barの引数がおかしい(){
    Foo::bar("hoge");
  }
}

みたいにテストしたい

解決策

class FooTest extends TestCase{
  protected function setUp(){
    assert_options(ASSERT_ACTIVE,true);
    assert_options(ASSERT_EXCEPTION,false);
    parent::setUp();
  }

  /**
   * @expectedException \PHPUnit\Framework\Error\Warning
   * @test
   */
  public function barの引数がおかしい(){
    Foo::bar("hoge");
  }
}

解説

assert()は、zend.assertionsが1かつassert.exceptionが0のとき、Fatal errorで死なずにWarningを出します。
PHPマニュアルにもあるように、本当はphp.iniでこれを制御します。しかし、たぶん本番環境ではzend.assertionsは0だし開発環境ではassert.exceptionは1なので、テストの時だけこれを変更するために非推奨assert_options()を使います。

PHPUnitでは、Fatal以外のエラーを例外に変換してくれるので、@expectedExceptionWarningを書けばassert()が働いていることを確認できます。

おわりに

assert()自体がテストなのにPHPUnitでそれをテストするの、本末転倒感がある。