How to PHPUnit test a method with no return value?

2020-05-23 07:05发布

问题:

I am trying to test methods from the following class I have written (there are more functions than what is shown, basically, one function for each is_*() method):

class Validate {
  private static $initialized = false;

  /**
  * Construct won't be called inside this class and is uncallable from the outside. This prevents
  * instantiating this class. This is by purpose, because we want a static class.
  */
  private function __construct() {}

  /**
  * If needed, allows the class to initialize itself
  */
  private static function initialize()
  {
    if(self::$initialized) {
      return;
    } else {
      self::$initialized = true;
      //Set any other class static variables here
    }
  }

  ...

  public static function isString($string) {
    self::initialize();
    if(!is_string($string)) throw new InvalidArgumentException('Expected a string but found ' . gettype($string));
  }

  ...

}

When I test if the methods throw an exception on invalid input, it works great! However, when I test if the method works as expected, PHPUnit complains because I have no assert in the test. The specific error is:

# RISKY This test did not perform any assertions

However, I don't have any value to assert against so I'm not sure how to overcome this.

I've read some about testing static methods, but that mostly seems to cover dependencies between static methods. Further, even non-static methods could have no return value, so, how to fix this?

For reference, my test code:

class ValidateTest extends PHPUnit_Framework_TestCase {
  /**
  * @covers ../data/objects/Validate::isString
  * @expectedException InvalidArgumentException
  */
  public function testIsStringThrowsExceptionArgumentInvalid() {
    Validate::isString(NULL);
  }

  /**
  * @covers ../data/objects/Validate::isString
  */
  public function testIsStringNoExceptionArgumentValid() {
    Validate::isString("I am a string.");
  }
}

回答1:

Test void function with assertNull:

    /**
     * @covers ../data/objects/Validate::isString
     */
    public function testIsStringNoExceptionArgumentValid() {
         $this->assertNull( Validate::isString("I am a string.") );
    }


回答2:

To prevent the warning about the assertions you can use the @doesNotPerformAssertions annotation as explained in the documentation: https://phpunit.de/manual/current/en/appendixes.annotations.html#idp1585440

Or if you prefer code over annotation: $this->doesNotPerformAssertions();



回答3:

One solution I have come upon is the following, based on example 2.12 from chapter 2 of PHPUnit. It feels a little hacky to me, but it's the best I've found so far. Also, based on this PHPUnit Gitub issue discussion, it seems several other people want this feature but that there are no plans to implement it.

Change testIsStringNoExceptionArgumentValid() to the following:

  /**
  * @covers ../data/objects/Validate::isString
  */
  public function testIsStringNoExceptionArgumentValid() {
    try {
      Validate::isString("I am a string.");
    } catch (InvalidArgumentException $notExpected) {
      $this->fail();
    }

    $this->assertTrue(TRUE);
  }