Msencenb
Msencenb

Reputation: 5104

Custom exception not found by PHPUnit with Laravel 5.2

I'm trying to throw a new custom exception, and write the test to ensure it actually gets thrown. I've created a new exception at the following location App\Exceptions\AgreementsNotSignedException.php

<?php

namespace App\Exceptions;

class AgreementsNotSignedException extends \Exception {}

and my order's 'checkout' method looks like this:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Exceptions\AgreementsNotSignedException as AgreementsNotSignedException;

class Order extends Model
{
    public function checkout() 
    {
        throw new AgreementsNotSignedException("User must agree to all agreements prior to checkout.");
    }
}

My basic test that is failing looks like this:

<?php

use App\Order;
use App\Exceptions\AgreementsNotSignedException;

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class OrderTest extends TestCase {
     /** @test * */
    function it_does_not_allow_the_user_to_checkout_with_unsigned_contracts()
    {
        $exceptionClass = get_class(new App\Exceptions\AgreementsNotSignedException());
        $this->setExpectedException(
            $exceptionClass, 'User must agree to all agreements prior to checkout.'
        );

        try {
            $this->order->checkout();
        } catch (App\Exceptions\AgreementsNotSignedException $exception) {
            $this->assertNotEquals($this->order->status, "completed");
        }
    }
}

The message spit out is 'Failed asserting that exception of type "App\Exceptions\AgreementsNotSignedException" is thrown.'. However I can verify via xdebug that the exception is indeed caught. As Jeff stated in the comments, it appears to be a FQN problem, as doing this makes the test pass:

 /** @test * */
function it_does_not_allow_the_user_to_checkout_with_unsigned_contracts()
{
    $exceptionClass = get_class(new App\Exceptions\AgreementsNotSignedException());
    $this->setExpectedException(
            $exceptionClass, 'User must agree to all agreements prior to checkout.'
        );

    throw new App\Exceptions\AgreementsNotSignedException('User must agree to all agreements prior to checkout.');
}

I'll keep poking around by changing the FQN, but any guidance would be awesome.

Upvotes: 1

Views: 473

Answers (2)

Jim M
Jim M

Reputation: 4341

Just had the same problem and found the solution, based on the source code, PhpUnit's $this->setExpectedException() method is deprecated.

* * @since Method available since Release 3.2.0 * @deprecated Method deprecated since Release 5.2.0 */ public function setExpectedException($exception, $message = '', $code = null) {

I used $this->expectException(MyCustomException::class) instead and it worked.

Upvotes: 1

Matteo
Matteo

Reputation: 39390

try with:

$this->setExpectedException(
            'App\Exceptions\AgreementsNotSignedException, 'User must agree to all agreements prior to checkout.'
        );

instead of this:

$exceptionClass = get_class(new App\Exceptions\AgreementsNotSignedException());
        $this->setExpectedException(
            $exceptionClass, 'User must agree to all agreements prior to checkout.'
        );

Upvotes: 0

Related Questions