Laravel如何使用Mockery伪造对象进行单元测试

发布时间 - 2025-11-15 00:00:00    点击率:
使用Mockery可在Laravel中模拟依赖对象,如PaymentGateway,通过伪造、设定期望行为、注入和断言来测试OrderService逻辑,避免真实调用外部服务。利用shouldReceive、with、andReturn等方法定义模拟行为,并通过$this->instance()将模拟对象绑定到容器,实现对控制器的测试,确保代码单元独立且可预测。

在Laravel中使用Mockery进行单元测试,主要是为了隔离外部依赖,比如数据库、队列、第三方API等,从而专注于测试当前类的行为。Mockery是一个强大的PHP模拟框架,与PHPUnit集成良好,Laravel也原生支持它。

安装与启用Mockery

Laravel项目通常已经内置了Mockery,如果你使用的是Laravel自带的测试工具集(如Pest或PHPUnit),无需额外安装。若需手动安装,可通过Composer:

composer require --dev mockery/mockery

Laravel的测试基类 TestCase 已经集成了Mockery,每次测试结束后会自动清理模拟对象。

基本用法:伪造一个服务类

假设你有一个订单服务 OrderService,它依赖于一个支付网关 PaymentGateway。你想测试下单逻辑而不真正调用支付接口。

定义服务类示例:

class PaymentGateway
{
    public function charge($amount)
    {
        // 实际调用第三方API
    }
}

class OrderService
{
    protected $gateway;

    public function __construct(PaymentGateway $gateway)
    {
        $this->gateway = $gateway;
    }

    public function createOrder($amount)
    {
        $result = $this->gateway->charge($amount);
        return $result ? ['status' => 'success'] : ['status' => 'failed'];
    }
}

编写测试,使用Mockery伪造PaymentGateway:

use Mockery;
use Tests\TestCase;

class OrderServiceTest extends TestCase
{
    public function tearDown(): void
    {
        Mockery::close(); // Laravel通常自动处理
    }

    public function test_it_can_create_order_when_payment_succeeds()
    {
        // 创建模拟对象
        $mockGateway = Mockery::mock('App\Services\PaymentGateway');

        // 定义期望行为
        $mockGateway->shouldReceive('charge')
                    ->with(100)
                    ->andReturn(true);

        // 注入模拟对象
        $service = new OrderService($mockGateway);

        // 执行测试
        $result = $service->createOrder(100);

        // 断言结果
        $this->assertEquals('success', $result['status']);
    }
}

在Laravel容器中绑定模拟对象

如果服务是通过Laravel服务容器自动注入的(例如在控制器中),可以使用 $this->instance() 方法将模拟对象绑定到容器:

public function test_controller_action_with_mocked_service()
{
    $mockGateway = Mockery::mock('App\Services\PaymentGateway');
    $mockGateway->shouldReceive('charge')->with(50)->andReturn(true);

    // 将模拟对象注入容器
    $this->instance('App\Services\PaymentGateway', $mockGateway);

    // 调用路由或控制器
    $response = $this->post('/orders', ['amount' => 50]);

    $response->assertStatus(200);
    $response->assertJson(['status' => 'success']);
}

或者使用 app()->instance() 实现相同效果。

常用Mockery方法

  • shouldReceive('method'):声明某个方法将被调用
  • with($arg):断言传入参数
  • andReturn($value):指定返回值
  • andReturnNull():返回null
  • andReturnUsing(Closure):动态返回值
  • times(n):断言调用次数
  • once()twice():简化调用次数断言
  • andReturnSelf():链式调用支持

例如:

$mock = Mockery::mock('SomeClass');
$mock->shouldReceive('process')
     ->with('data')
     ->andReturnUsing(function ($arg) {
         return strtoupper($arg);
     });

基本上就这些。只要理解“伪造对象 → 设定期望 → 注入使用 → 断言行为”的流程,就能高效地为复杂依赖写测试。Laravel + Mockery组合让单元测试更轻量可控。


# php  # laravel  # js  # json  # composer  # app  # 工具  # ai  # 路由  # gate  # NULL  # require  # 接口  # 对象  # this  # 数据库  # 绑定  # 链式  # 第三方  # 返回值  # 的是  # 是一个  # 单元测试  # 如果你  # 就能  # 你想 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在宝塔面板中修改默认建站目录?  Laravel如何实现本地化和多语言支持?(i18n教程)  Laravel控制器是什么_Laravel MVC架构中Controller的作用与实践  Python高阶函数应用_函数作为参数说明【指导】  如何在Windows虚拟主机上快速搭建网站?  免费网站制作appp,免费制作app哪个平台好?  千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  网易LOFTER官网链接 老福特网页版登录地址  香港网站服务器数量如何影响SEO优化效果?  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  谷歌Google入口永久地址_Google搜索引擎官网首页永久入口  Laravel如何实现API版本控制_Laravel API版本化路由设计策略  如何确保FTP站点访问权限与数据传输安全?  如何快速使用云服务器搭建个人网站?  如何在云指建站中生成FTP站点?  如何快速搭建安全的FTP站点?  详解Oracle修改字段类型方法总结  Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解  javascript中对象的定义、使用以及对象和原型链操作小结  EditPlus 正则表达式 实战(3)  JavaScript实现Fly Bird小游戏  laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法  如何在 React 中条件性地遍历数组并渲染元素  Laravel如何实现用户密码重置功能?(完整流程代码)  焦点电影公司作品,电影焦点结局是什么?  如何在IIS中新建站点并配置端口与物理路径?  Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】  php json中文编码为null的解决办法  如何为不同团队 ID 动态生成多个非值班状态按钮  Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】  Windows Hello人脸识别突然无法使用  js代码实现下拉菜单【推荐】  EditPlus中的正则表达式实战(5)  如何在建站之星网店版论坛获取技术支持?  太平洋网站制作公司,网络用语太平洋是什么意思?  车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  教你用AI将一段旋律扩展成一首完整的曲子  Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  如何用花生壳三步快速搭建专属网站?  Python结构化数据采集_字段抽取解析【教程】  如何利用DOS批处理实现定时关机操作详解  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  Laravel如何使用Eloquent进行子查询  手机网站制作与建设方案,手机网站如何建设?