使用 Laravel 5.2 的 PHPUnit 未找到自定义异常

Posted

技术标签:

【中文标题】使用 Laravel 5.2 的 PHPUnit 未找到自定义异常【英文标题】:Custom exception not found by PHPUnit with Laravel 5.2 【发布时间】:2016-09-23 12:36:33 【问题描述】:

我正在尝试抛出一个新的自定义异常,并编写测试以确保它确实被抛出。我在以下位置创建了一个新异常 App\Exceptions\AgreementsNotSignedException.php

<?php

namespace App\Exceptions;

class AgreementsNotSignedException extends \Exception 

我的订单的“结帐”方法如下所示:

<?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.");
    

我失败的基本测试如下所示:

<?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");
        
    

吐出的消息是“断言“App\Exceptions\AgreementsNotSignedException”类型的异常被抛出失败。但是我可以通过 xdebug 验证确实捕获了异常。正如 Jeff 在 cmets 中所说,这似乎是一个 FQN 问题,因为这样做会使测试通过:

 /** @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.');

我会通过更改 FQN 继续探索,但任何指导都会很棒。

【问题讨论】:

需要指定预期异常的全限定命名空间,如this question OrderTest类中的$this->order是如何定义的? 这是一个受保护的变量,在 setup 方法中被赋值(图中未显示)。 order 变量很好,我可以在调用 checkout 之前使用调试器验证它的状态。 【参考方案1】:

刚遇到同样的问题,找到了解决办法,根据源码,PhpUnit的$this-&gt;setExpectedException()方法已弃用。

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

我改用了 $this-&gt;expectException(MyCustomException::class),它成功了。

【讨论】:

【参考方案2】:

尝试:

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

而不是这个:

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

【讨论】:

不幸的是同样的错误。我首先尝试过这个,然后使用 get_class 方法,希望它能更好地限定事情。我已经设法使用 assertThat 和 PHPUnit_Framework_Constraint_Exception 让这个测试工作。

以上是关于使用 Laravel 5.2 的 PHPUnit 未找到自定义异常的主要内容,如果未能解决你的问题,请参考以下文章

使用 Laravel 5.2 的 PHPUnit 未找到自定义异常

Laravel 5.2 PHPUnit JSON Api 请求正文未设置

Laravel 5:PHPUnit 和没有可用的代码覆盖驱动程序

在laravel 5.2中使用工厂关系违反完整性约束

使用 phpunit 进行 Laravel 测试

在没有 /vendor/bin/ 的 laravel 4 中使用 phpunit