How do I test for an exact Exception message, rather than a substring, with PHPUnit?

后端 未结 6 1720
难免孤独
难免孤独 2021-01-12 07:14

According to the PHPUnit Documentation on @expectedExceptionMessage, the string must only be a substring of the actual Exception thrown.

In

相关标签:
6条回答
  • 2021-01-12 07:22

    You can use $this->expectExceptionMessage to handle this.

    Example:

    $this->expectException(InvalidArgumentException::class);
    $this->expectExceptionMessage = "Some error message";
    
    0 讨论(0)
  • 2021-01-12 07:27

    When this question was posted, PHPUnit v3.7 didn't have a solution to this problem. Newer versions have a new @expectedExceptionMessageRegExp option that you can use to add a regular expression to match the exception message against.

    Your case, using ^ and $ to force the string to be exactly what is expected, could look like this:

    /**
     * @expectedException \Exception
     * @expectedExceptionMessageRegExp /^a < b\.$/
     */
    public function testValues_ALessBOnly()
    {
        $myClass = new MyClass()
        $myClass->validate(1, 2, 4, 3);
    }
    
    0 讨论(0)
  • 2021-01-12 07:30

    Another possible solution, to make sure that error have happened:

            $errorHappened = false;
            try {
                //call your code here 
            } catch (\Exception $e) {
                $errorHappened = true;
                $this->assertEquals($e->getMessage(), "Expected error text");
                $this->assertEquals($e->getCode(), "Expected error code");
            }
            $this->assertTrue($errorHappened);
    
    0 讨论(0)
  • 2021-01-12 07:31

    If your test class extends PHPUnit_Framework_TestCase, you should be able to use setExpectedException method:

        /**
         * @param mixed  $exceptionName
         * @param string $exceptionMessage
         * @param int    $exceptionCode
         *
         * @since  Method available since Release 3.2.0
         */
        public function setExpectedException($exceptionName, $exceptionMessage = '', $exceptionCode = null)
        {
            $this->expectedException        = $exceptionName;
            $this->expectedExceptionMessage = $exceptionMessage;
            $this->expectedExceptionCode    = $exceptionCode;
        }
    

    It allows you to assert an exception class alone, exception message and even exception code.

    0 讨论(0)
  • 2021-01-12 07:34

    I tried many ways to test exceptions and finally I found that the best way to test Exceptions is try-catch blocks. I suggest you to throw exceptions with exception code and then test if exception with this code is thrown. For example suppose that your exception code is 101

    if(count($errors) > 0) throw new \Exception(trim(implode(" ", $errors)), 101);
    

    For example suppose that your exception code is 101

    try {
        $myClass->validate(1, 2, 4, 3);
        $this->fail( "Exception with 101 code should be thrown" );
    } catch (Exception $e) {
        $this->assertEquals( 101, $e->getCode());
    }
    
    0 讨论(0)
  • 2021-01-12 07:44

    I normally do not worry about the text of the exception, but that the exception itself is thrown, so that an @expectedException can be used, and even a Data Provider for most error scenarios.

    The other change I make then is to do the tests (a < b) in a different function, and if a failure occurs, throw the exception, instead of combining them all and looking at the text. The different functions can then be tested on their own as well.

    From reading the PHPUnit manual, even the error thrown on assert uses the word 'contains', so it implies that it is a substring match. The same manual suggests writing the tests as you did above, so I believe that as long as you want to check the exception text, then according to the samples in the PHPUnit manual, you need to write the tests as you did.

    I would also caution from comparing the actual text, in case you add multiple language support in the future, the test will need to then understand the different languages/sentences returned. Simply checking the exception is thrown, will not suffer this problem.

    0 讨论(0)
提交回复
热议问题