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

Laravel 5.6控制器单元测试编写方法求助(附代码示例)

如何正确为Laravel 5.6的NewOrdersController编写单元测试

看起来你已经迈出了单元测试的第一步,不过你的测试代码里有几个小问题需要修正,同时我们可以完善测试覆盖的场景。下面一步步来解决:

原测试代码中的问题

  • 控制器实例化错误:你写的new newOrder($this->neworders)存在两个问题:一是控制器类名是NewOrdersController而非newOrder;二是你定义的Mock变量是$neworders,不是$this->neworders。
  • Mock接口的命名空间缺失:直接写'NewOrderRepositoryInterface'可能会导致类找不到,最好使用完整的命名空间(比如App\Repositories\NewOrderRepositoryInterface,根据你实际的命名空间调整)。
  • 测试场景不完整:你的控制器有两种返回逻辑(订单为空返回0,不为空返回1),原测试只覆盖了一种情况。
  • Mock返回值不符合逻辑:原控制器通过count($orders)判断订单数量,你返回0的话count(0)结果是1,不会触发返回0的分支。

修正后的完整测试代码

use Mockery;
use App\Http\Controllers\NewOrdersController;
use App\Repositories\NewOrderRepositoryInterface; // 替换成你项目中的实际命名空间

class NewOrderTest extends TestCase
{
    public function tearDown()
    {
        Mockery::close();
        parent::tearDown(); // 别忘了调用父类的清理逻辑
    }

    /** @test */
    public function order_list_returns_0_when_no_orders_exist()
    {
        // 1. 创建接口的Mock实例
        $newOrdersRepo = Mockery::mock(NewOrderRepositoryInterface::class);
        
        // 2. 设置Mock的方法期望:调用getNewOrders一次,返回空数组(触发count为0的分支)
        $newOrdersRepo->shouldReceive('getNewOrders')
            ->once()
            ->andReturn([]);

        // 3. 实例化控制器并注入Mock依赖
        $controller = new NewOrdersController($newOrdersRepo);

        // 4. 断言返回值符合预期
        $this->assertEquals(0, $controller->orderList());
    }

    /** @test */
    public function order_list_returns_1_when_orders_exist()
    {
        $newOrdersRepo = Mockery::mock(NewOrderRepositoryInterface::class);
        
        // 返回非空数组,模拟有订单的情况
        $newOrdersRepo->shouldReceive('getNewOrders')
            ->once()
            ->andReturn([(object)['id' => 1, 'order_no' => 'ORD-001']]);

        $controller = new NewOrdersController($newOrdersRepo);

        $this->assertEquals(1, $controller->orderList());
    }
}

关键细节说明

  • Mock返回值匹配逻辑:原控制器通过count($orders)判断订单数量,所以模拟无订单时要返回空数组,模拟有订单时返回非空数组,这样才能正确触发对应的分支。
  • 命名空间一致性:务必确保NewOrderRepositoryInterface的命名空间和你项目中的实际文件路径一致,否则会出现类找不到的错误。
  • 覆盖所有代码分支:单元测试要覆盖控制器的全部逻辑分支,这样才能验证你的代码在各种场景下都能正常工作。
  • 父类清理逻辑:Laravel的TestCase父类自带测试环境清理逻辑,所以在自定义的tearDown方法里要调用parent::tearDown(),避免测试污染。

内容的提问来源于stack exchange,提问作者Avik Pradhan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:41:34