我在尝试测试涉及数据库交互的 Laravel 控制器中的异常处理时遇到问题。具体来说,我想在控制器的 store 方法中测试异常的 catch 块。存储方法如下所示:
public function store(Request $request, Pipeline $pipeline)
{
try {
$request->validate([
"name" => ["required", "max:512"],
"stage" => ["required", "in:".Stage::toCSV()],
]);
// Database interaction here (e.g., MyModel::create())
return response()->json(["message" => trans("round.created")], 201);
} catch (\Exception $e) {
Log::error('Exception in MyController@store: ' . $e->getMessage());
Log::error('Stack trace: ' . $e->getTraceAsString());
return redirect()->back()->banner(trans('error'));
}
}
这是我迄今为止尝试过的
$this->mock(\App\Models\MyModel::class, function ($mock) {
$mock->shouldReceive('create')
->once()
->andThrow(new \Exception('Simulated exception'));
});
$this->mock(\Exception::class, function ($mock) {
$mock->shouldReceive('getMessage')->andReturn('Mocked exception message');
});
任何关于如何正确模拟数据库交互以模拟异常并测试 catch 块的建议或指导将不胜感激。
谢谢!
在 Laravel 控制器的 store 方法中测试异常的 catch 块的最佳方法是模拟数据库交互,以便引发异常。为此,您需要模拟 MyModel 类以在创建方法调用期间引发异常 为此,我建议将模型作为控制器的依赖项注入,这样您就可以创建一个模拟模型并通过它并测试其功能
use App\Models\MyModel;
class MyController extends Controller
{
public function store(Request $request, MyModel $model, Pipeline $pipeline)
{
try {
$request->validate([
"name" => ["required", "max:512"],
"stage" => ["required", "in:".Stage::toCSV()],
]);
// Use the injected model for database interaction
$model->create([
// Your data here
]);
return response()->json(["message" => trans("round.created")], 201);
} catch (\Exception $e) {
Log::error('Exception in MyController@store: ' . $e->getMessage());
Log::error('Stack trace: ' . $e->getTraceAsString());
return redirect()->back()->banner(trans('error'));
}
}
}
或者您可以采用基于服务的方法。 在这两种情况下,您都可以模拟模型/服务,然后将模拟的依赖项注入控制器并测试它
要创建模拟,您可以使用模拟构建器或模拟或
匿名类
$modelMock = new class extends MyModel {
public static function create(array $attributes = [])
{
// Throw an exception when create is called
throw new \Exception('Simulated exception');
}
};