戻り値がないメソッドを検証できるAssertがあってもいいよね

こういうクラスがあるとする

<?php

class Hoge
{
  public function fuga(int $id): void
  {
    if (1 === $id) {
      // early return
      return;
    }
    // なんか適当にDBインサート処理とか処理する
    DB::insert($id);
  }
}

これのテストを書く

<?php

class Hoge
{
  use PHPUnit\Framework\TestCase;

  /**
    *@test
    */
  public function idを渡すとほげふがすること()
  {
    $hoge = new Hoge();
    // 実行。1の時はearly returnするため何もせず終わる
    $hoge->fuga(2);

    // 処理に対してassertionしてあげたらOK
    $data = DB::getData(2);
    $this->assertNotNull($data);
  }

  /**
    *@test
    */
  public function idが1の時は処理しないこと()
  {
    $hoge = new Hoge();
    // 実行。1の時はearly returnするため何もせず終わる
    $hoge->fuga(1);
    
    // 戻り値がないのでassertionできなくて、riskyテスト扱いになる
  }
}

early returnのケースでテストを書く場合、何が適切かふわっとしている

対処法

  1. @doesNotPerformAssertionsつける
    riskyテスト扱いじゃなくなる、1テストとしてちゃんとカウントもされる
  2. $this->assertTrue(true)とかで"例外が無く処理できていること"を担保する
    コメント必須な気がする、あとなにか修正入れた場合に気づかないかもしれない
  3. テスト自体書かない
    何もしないのでテストを書かないのはある意味正しいかもしれないけど、カバレッジ的にはダメそう
  4. fugaメソッドで適当にboolとか返しちゃう
    本末転倒、なしである

結局1でも2でもearly returnで処理が動かないことを説明する必要があるので、コメントは必須になりそう
3が理解されてもらえたら結構いいけど、early returnに処理追加したりしたときにテストないのはちょっと怖い
4はなしである

こんなのあったらいいよね妄想

assertVoidReturn() みたいなvoidを検証するオシャレなのを定義しちゃう

<?php

class Hoge
{
  use PHPUnit\Framework\TestCase;

  /**
    *@test
    */
  public function idが1の時は処理しないこと()
  {
    $hoge = new Hoge();
    // early returnでvoidが返っていることを検証できる
    $this->assertVoidReturn($hoge->fuga(1));
  }
}

ただ問題点として

  • void代入したらnullになっちゃう
    https://3v4l.org/tSnaZ
  • そもそもvoidを持てる言語はあるのか

みたいなところがあるので妄想止まり