Laravel 事件派发断言失败
Laravel event dispatch assertion fails
我正在编写一些单元测试来测试数据库事务中间件,在出现异常时,事务中的所有内容都应该进行回滚。并且这段代码工作得很好并且通过了单元测试:
成功的单元测试方法
public function testTransactionShouldRollback()
{
Event::fake();
// Ignore the exception so the test itself can continue.
$this->expectException('Exception');
$this->middleware->handle($this->request, function () {
throw new Exception('Transaction should fail');
});
Event::assertDispatched(TransactionRolledBack::class);
}
然而,每当我测试一个 TransactionBeginning
事件时,它都无法断言该事件已被调度。
失败的单元测试方法
public function testTransactionShouldBegin()
{
Event::fake();
$this->middleware->handle($this->request, function () {
return $this->response;
});
Event::assertDispatched(TransactionBeginning::class);
}
实际的中间件
public function handle($request, Closure $next)
{
DB::beginTransaction();
try {
$response = $next($request);
if ($response->exception) {
throw $response->exception;
}
} catch (Throwable $e) {
DB::rollBack();
throw $e;
}
if (!$response->exception) {
DB::commit();
}
return $response;
}
所有事务事件都会触发事件,因此 DB::beginTransaction, DB::rollBack, DB::commit
应该会触发所有事件。然而,当我测试时,我什至只看到事务回滚事件触发。
在这种情况下其他事件没有触发并且我的 assertDispatched 失败是否有原因?
我不知道确切原因(必须深入挖掘),但我找到了解决此问题的方法。
似乎这里仍然使用默认事件调度程序,所以当您 运行 Event::fake()
数据库连接使用默认调度程序时。解决方案不是 运行ning 只是:
Event::fake();
到运行:
$fake = Event::fake();
DB::setEventDispatcher($fake);
经过这样的修改,对我来说测试 运行 没问题。下面是完整的测试用例 class:
<?php
namespace Tests\Feature;
use App\Http\Middleware\TestMiddleware;
use Exception;
use Illuminate\Database\Events\TransactionBeginning;
use Illuminate\Database\Events\TransactionCommitted;
use Illuminate\Database\Events\TransactionRolledBack;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* @var \App\Http\Middleware\TestMiddleware
*/
protected $middleware;
/**
* @var \Illuminate\Http\Request
*/
protected $request;
/**
* @var \Illuminate\Http\Response
*/
protected $response;
public function setUp():void
{
parent::setUp();
Event::fake();
$this->middleware = new TestMiddleware();
$this->request = new Request();
$this->response = new Response();
}
public function testTransactionShouldRollback()
{
$fake = Event::fake();
DB::setEventDispatcher($fake);
// Ignore the exception so the test itself can continue.
$this->expectException('Exception');
$this->middleware->handle($this->request, function () {
throw new Exception('Transaction should fail');
});
Event::assertDispatched(TransactionBeginning::class);
Event::assertDispatched(TransactionRolledBack::class);
Event::asserNotDispatched(TransactionCommitted::class);
}
public function testTransactionShouldBegin()
{
$fake = Event::fake();
DB::setEventDispatcher($fake);
$this->middleware->handle($this->request, function () {
return $this->response;
});
Event::assertDispatched(TransactionBeginning::class);
Event::assertNotDispatched(TransactionRolledBack::class);
Event::assertDispatched(TransactionCommitted::class);
}
}
我正在编写一些单元测试来测试数据库事务中间件,在出现异常时,事务中的所有内容都应该进行回滚。并且这段代码工作得很好并且通过了单元测试:
成功的单元测试方法
public function testTransactionShouldRollback()
{
Event::fake();
// Ignore the exception so the test itself can continue.
$this->expectException('Exception');
$this->middleware->handle($this->request, function () {
throw new Exception('Transaction should fail');
});
Event::assertDispatched(TransactionRolledBack::class);
}
然而,每当我测试一个 TransactionBeginning
事件时,它都无法断言该事件已被调度。
失败的单元测试方法
public function testTransactionShouldBegin()
{
Event::fake();
$this->middleware->handle($this->request, function () {
return $this->response;
});
Event::assertDispatched(TransactionBeginning::class);
}
实际的中间件
public function handle($request, Closure $next)
{
DB::beginTransaction();
try {
$response = $next($request);
if ($response->exception) {
throw $response->exception;
}
} catch (Throwable $e) {
DB::rollBack();
throw $e;
}
if (!$response->exception) {
DB::commit();
}
return $response;
}
所有事务事件都会触发事件,因此 DB::beginTransaction, DB::rollBack, DB::commit
应该会触发所有事件。然而,当我测试时,我什至只看到事务回滚事件触发。
在这种情况下其他事件没有触发并且我的 assertDispatched 失败是否有原因?
我不知道确切原因(必须深入挖掘),但我找到了解决此问题的方法。
似乎这里仍然使用默认事件调度程序,所以当您 运行 Event::fake()
数据库连接使用默认调度程序时。解决方案不是 运行ning 只是:
Event::fake();
到运行:
$fake = Event::fake();
DB::setEventDispatcher($fake);
经过这样的修改,对我来说测试 运行 没问题。下面是完整的测试用例 class:
<?php
namespace Tests\Feature;
use App\Http\Middleware\TestMiddleware;
use Exception;
use Illuminate\Database\Events\TransactionBeginning;
use Illuminate\Database\Events\TransactionCommitted;
use Illuminate\Database\Events\TransactionRolledBack;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* @var \App\Http\Middleware\TestMiddleware
*/
protected $middleware;
/**
* @var \Illuminate\Http\Request
*/
protected $request;
/**
* @var \Illuminate\Http\Response
*/
protected $response;
public function setUp():void
{
parent::setUp();
Event::fake();
$this->middleware = new TestMiddleware();
$this->request = new Request();
$this->response = new Response();
}
public function testTransactionShouldRollback()
{
$fake = Event::fake();
DB::setEventDispatcher($fake);
// Ignore the exception so the test itself can continue.
$this->expectException('Exception');
$this->middleware->handle($this->request, function () {
throw new Exception('Transaction should fail');
});
Event::assertDispatched(TransactionBeginning::class);
Event::assertDispatched(TransactionRolledBack::class);
Event::asserNotDispatched(TransactionCommitted::class);
}
public function testTransactionShouldBegin()
{
$fake = Event::fake();
DB::setEventDispatcher($fake);
$this->middleware->handle($this->request, function () {
return $this->response;
});
Event::assertDispatched(TransactionBeginning::class);
Event::assertNotDispatched(TransactionRolledBack::class);
Event::assertDispatched(TransactionCommitted::class);
}
}