You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel PHPUnit如何测试含真实/假数据的Excel文件导入功能

Laravel Excel导入功能PHPUnit测试异常排查与解决

问题概述

在Laravel项目中使用MaatWebsite/Excel实现图书Excel导入功能,生产环境上传文件可正常导入数据库,但PHPUnit测试导入路由时出现异常:

  • 测试代码尝试读取test/Files/bookdata.xlsx真实文件,但请求失败
  • 开启withoutExceptionHandling()后,程序卡在异常处理环节
  • 尝试生成假Excel文件时,无内容的文件触发业务报错,且不知道如何生成带有效内容的假文件

测试使用的Excel文件内容:

categoryBook CodeBook TitleAuthorPublisherDescriptionStock
1CO4D3ETittle 1Ex.Name1Publish1BookDesc13
33XA8PLTittle 2Ex.Name2Publish2BookDesc21

错误原因分析

1. 真实文件上传方式错误

测试代码中用UploadedFile::fake()->create()加载真实文件是错误的,该方法用于生成假文件,而非读取本地真实文件,正确做法是用UploadedFile实例直接加载真实文件路径。

2. 路由调用错误

测试中post('book.import')将字符串当作URL路径,而非路由名称,正确的路由调用应使用route('book.import')生成合法URL。

3. Excel模拟与真实导入冲突

Excel::fake()会模拟Excel导入行为,不会执行真实的文件解析逻辑。若要测试真实导入业务(如数据入库),需移除Excel::fake(),或配合模拟断言使用。

4. 控制器方法调用错误

控制器中$import->getRowCount缺少方法调用括号(),导致传递给通知的是方法对象而非行数值,触发潜在错误。

修正后的测试代码

方案1:使用真实文件测试完整业务逻辑

public function test_book_import(): void
{
    // 预创建分类数据,匹配Excel中的category值
    Categories::factory(6)->create();
    
    // 加载真实Excel文件
    $filePath = base_path('test/Files/bookdata.xlsx');
    $file = new UploadedFile(
        $filePath,
        'bookdata.xlsx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        null,
        true // 标记为测试环境上传,绕过文件大小限制
    );

    // 发送请求到正确路由
    $response = $this->post(route('book.import'), ['file' => $file]);

    // 断言重定向和成功提示
    $response->assertRedirect(route('book.create'));
    $response->assertSessionHas('success', 'Excel file imported successfully!');

    // 断言数据库导入数据正确性
    $this->assertDatabaseCount('books', 2);
    $this->assertDatabaseHas('books', [
        'book_code' => 'CO4D3E',
        'book_title' => 'Tittle 1',
        'stock' => 3
    ]);
}

方案2:生成带内容的假Excel文件测试

若不想依赖真实文件,可通过PhpSpreadsheet生成带内容的假文件:

public function test_book_import_with_fake_file(): void
{
    Categories::factory(6)->create();

    // 生成假Excel内容
    $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();
    // 写入表头
    $sheet->setCellValue('A1', 'category');
    $sheet->setCellValue('B1', 'Book Code');
    $sheet->setCellValue('C1', 'Book Title');
    $sheet->setCellValue('D1', 'Author');
    $sheet->setCellValue('E1', 'Publisher');
    $sheet->setCellValue('F1', 'Description');
    $sheet->setCellValue('G1', 'Stock');
    // 写入数据行
    $sheet->setCellValue('A2', 1);
    $sheet->setCellValue('B2', 'CO4D3E');
    $sheet->setCellValue('C2', 'Tittle 1');
    $sheet->setCellValue('D2', 'Ex.Name1');
    $sheet->setCellValue('E2', 'Publish1');
    $sheet->setCellValue('F2', 'BookDesc1');
    $sheet->setCellValue('G2', 3);

    // 保存到临时文件
    $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
    $tempFile = tempnam(sys_get_temp_dir(), 'excel');
    $writer->save($tempFile);

    // 创建UploadedFile对象
    $file = new UploadedFile(
        $tempFile,
        'fake_bookdata.xlsx',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        null,
        true
    );

    $response = $this->post(route('book.import'), ['file' => $file]);

    // 断言逻辑
    $response->assertRedirect(route('book.create'));
    $response->assertSessionHas('success', 'Excel file imported successfully!');
    $this->assertDatabaseCount('books', 1);
}

控制器代码修正

修正getRowCount的调用方式:

// 原代码
Notification::send($users, new ImportBookNotification($import->getRowCount));
// 修正后
Notification::send($users, new ImportBookNotification($import->getRowCount()));

测试Excel导入的实用技巧

  • 区分模拟与真实测试:
    • 用Excel::fake()可快速验证导入动作是否触发(如Excel::assertImported('filename.xlsx')),适合测试请求流程,无需关心文件内容
    • 若要验证业务逻辑(数据入库、行计数等),需使用真实文件或生成带内容的假文件,不要启用Excel::fake()
  • 开启异常处理排查:测试时临时开启$this->withoutExceptionHandling(),可直接查看具体错误信息(如文件不存在、数据验证失败等),避免卡在异常处理环节
  • 验证数据完整性:除断言重定向和session消息,务必断言数据库数据是否符合预期,确保导入逻辑正确
  • 复用测试数据:封装生成假Excel的逻辑为测试辅助方法,在多个测试用例中复用

内容的提问来源于stack exchange,提问作者Kholid Syaifullah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:17:05