Ste*_*n-v 6 php phpunit laravel laravel-events laravel-6
我正在编写一些单元测试来测试数据库事务中间件,出现异常时事务中的所有内容都应该回滚。这段代码工作得很好并且通过了单元测试:
成功的单元测试方法
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);
}
Run Code Online (Sandbox Code Playgroud)
然而,每当我测试一个TransactionBeginning事件时,它都无法断言该事件已被调度。
失败的单元测试方法
public function testTransactionShouldBegin()
{
Event::fake();
$this->middleware->handle($this->request, function () {
return $this->response;
});
Event::assertDispatched(TransactionBeginning::class);
}
Run Code Online (Sandbox Code Playgroud)
实际的中间件
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;
}
Run Code Online (Sandbox Code Playgroud)
所有事务事件都会触发事件,DB::beginTransaction, DB::rollBack, DB::commit所有触发事件也应如此。然而,当我测试时,我什至只看到事务回滚事件触发。
在这种情况下其他事件没有触发并且我的assertDispatched失败是否有原因?
我不知道确切的原因(必须更深入地挖掘),但我找到了解决此问题的解决方案。
似乎这里仍然使用默认事件调度程序,因此当您运行Event::fake()数据库连接时使用默认调度程序。解决方案不是仅仅运行:
Event::fake();
Run Code Online (Sandbox Code Playgroud)
跑步:
$fake = Event::fake();
DB::setEventDispatcher($fake);
Run Code Online (Sandbox Code Playgroud)
经过这样的修改后,我的测试运行良好。下面是完整的测试用例类:
<?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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6165 次 |
| 最近记录: |