处理来自 PHPUnit (Laravel 5.2) 的自定义异常

Posted

技术标签:

【中文标题】处理来自 PHPUnit (Laravel 5.2) 的自定义异常【英文标题】:Handling Custom Exceptions from PHPUnit (Laravel 5.2) 【发布时间】:2016-12-04 09:21:51 【问题描述】:

我目前正在使用异常处理程序,并创建自己的自定义异常。

我一直在使用 phpUnit 在我的控制器资源上运行测试,但是当我抛出自定义异常时,Laravel 认为它来自常规 HTTP 请求而不是 AJAX。

异常会根据是否是 AJAX 请求返回不同的响应,如下所示:

<?php namespace Actuame\Exceptions\Castings;

use Illuminate\Http\Request;

use Exception;

use Actuame\Exceptions\ExceptionTrait;

class Already_Applied extends Exception 


    use ExceptionTrait;

    var $redirect = '/castings';
    var $message = 'castings.errors.already_applied';


ExceptionTrait 如下:

<?php

namespace Actuame\Exceptions;

trait ExceptionTrait 


    public function response(Request $request)
    
        $type = $request->ajax() ? 'ajax' : 'redirect';

        return $this->$type($request);
    

    private function ajax(Request $request)
    
        return response()->json(array('message' => $this->message), 404);
    

    private function redirect(Request $request)
    
        return redirect($this->redirect)->with('error', $this->message);
    


最后,我的测试是这样的(失败的测试的摘录)

public function testApplyToCasting()

    $faker = Factory::create();

    $user = factory(User::class)->create();

    $this->be($user);

    $casting = factory(Casting::class)->create();

    $this->json('post', '/castings/apply/' . $casting->id, array('message' => $faker->text(200)))
        ->seeJsonStructure(array('message'));

我的逻辑是这样的虽然我不认为错误来自这里

public function apply(Request $request, User $user)

    if($this->hasApplicant($user))
        throw new Already_Applied;

    $this->get()->applicants()->attach($user, array('message' => $request->message));

    event(new User_Applied_To_Casting($this->get(), $user));

    return $this;

运行 PHPUnit 时,我得到的错误是

1) CastingsTest::testApplyToCasting PHPUnit_Framework_Exception: PHPUnit_Framework_Assert 的参数 #2(无值): :assertArrayHasKey() 必须是数组或ArrayAccess

/home/vagrant/Code/actuame2/vendor/laravel/framework/src/Illuminate/Foundation/T esting/Concerns/MakesHttpRequests.php:304 /home/vagrant/Code/actuame2/tests/CastingsTest.php:105

我的 laravel.log 在这里http://pastebin.com/ZuaRaxkL (太大无法粘贴)

我实际上发现 PHPUnit 实际上并没有发送 AJAX 响应,因为我的 ExceptionTrait 实际上改变了对此的响应。运行测试时,它将请求作为常规 POST 请求,并运行 redirect() 响应而不是 ajax(),因此它不会返回对应的。

非常感谢!

【问题讨论】:

【参考方案1】:

我终于找到了解决办法!

正如我所说,响应不是正确的,因为它试图重定向而不是返回有效的 JSON 响应。

在查看Request代码后,我发现我也需要使用wantsJson(),因为ajax()可能并非总是如此,所以我已将我的 trait 修改为:

<?php

namespace Actuame\Exceptions;

trait ExceptionTrait 


    public function response(Request $request)
    
        // Below here, I added $request->wantsJson()
        $type = $request->ajax() || $request->wantsJson() ? 'ajax' : 'redirect';

        return $this->$type($request);
    

    private function ajax(Request $request)
    
        return response()->json(array('message' => $this->message), 404);
    

    private function redirect(Request $request)
    
        return redirect($this->redirect)->with('error', $this->message);
    


【讨论】:

以上是关于处理来自 PHPUnit (Laravel 5.2) 的自定义异常的主要内容,如果未能解决你的问题,请参考以下文章

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

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

Laravel 5 PHPUnit 测试 json 帖子

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

laravel 4 无法让 phpunit 测试工作

Phpunit:在 laravel 中处理验证异常