Laravel+Pest测试:如何配置Mockery按方法调用参数返回对应值?
Laravel + Pest + Mockery 模拟 Dotenv 测试方案
核心思路
要实现针对Dotenv::createArrayBacked()的参数匹配,并让safeLoad()返回对应APP_URL,关键是利用Mockery的参数约束和链式调用模拟,同时通过Laravel容器替换真实的Dotenv实例。
具体实现步骤
1. 绑定模拟的Dotenv实例到容器
在测试用例中,先通过Mockery创建Dotenv的模拟对象,然后绑定到容器,确保Action中依赖注入的是模拟实例:
use Dotenv\Dotenv; beforeEach(function () { // 创建Dotenv的Mock实例 $dotenvMock = Mockery::mock(Dotenv::class); // 将Mock绑定到容器,覆盖真实实现 app()->instance(Dotenv::class, $dotenvMock); });
2. 匹配参数并指定返回值
针对不同的路径和文件名,用with()方法精确匹配参数,链式模拟safeLoad()返回对应环境变量数组:
it('returns correct APP_URL for .env.test', function () { $dotenvMock = app(Dotenv::class); // 模拟:传入base_path()和.env.test时,safeLoad返回指定APP_URL $dotenvMock->shouldReceive('createArrayBacked') ->with(base_path(), '.env.test') ->andReturnSelf() // 返回Mock自身,支持链式调用 ->shouldReceive('safeLoad') ->andReturn(['APP_URL' => 'https://test.example.com']); // 执行Action并断言结果 $action = app(YourEnvProcessingAction::class); $result = $action->handle(['test']); expect($result)->toHaveKey('test', 'https://test.example.com'); }); it('returns correct APP_URL for .env.staging', function () { $dotenvMock = app(Dotenv::class); $dotenvMock->shouldReceive('createArrayBacked') ->with(base_path(), '.env.staging') ->andReturnSelf() ->shouldReceive('safeLoad') ->andReturn(['APP_URL' => 'https://staging.example.com']); $action = app(YourEnvProcessingAction::class); $result = $action->handle(['staging']); expect($result)->toHaveKey('staging', 'https://staging.example.com'); });
3. 批量模拟多文件场景
如果需要一次性处理多个.env文件,可多次调用shouldReceive指定不同参数的返回逻辑:
it('handles multiple env files correctly', function () { $dotenvMock = app(Dotenv::class); // 模拟.test文件 $dotenvMock->shouldReceive('createArrayBacked') ->with(base_path(), '.env.test') ->andReturnSelf() ->shouldReceive('safeLoad') ->andReturn(['APP_URL' => 'https://test.example.com']) ->once(); // 模拟.staging文件 $dotenvMock->shouldReceive('createArrayBacked') ->with(base_path(), '.env.staging') ->andReturnSelf() ->shouldReceive('safeLoad') ->andReturn(['APP_URL' => 'https://staging.example.com']) ->once(); $action = app(YourEnvProcessingAction::class); $result = $action->handle(['test', 'staging']); expect($result)->toEqual([ 'test' => 'https://test.example.com', 'staging' => 'https://staging.example.com' ]); });
关键注意事项
- 确保Action通过依赖注入获取Dotenv实例,而非直接调用静态方法;如果是静态调用,需改用Mockery的静态模拟方式。
- 测试结束后Mockery会自动清理实例,也可在
afterEach中手动调用Mockery::close()避免残留。 - 若需模糊匹配路径,可用
Mockery::type('string')替代精确路径,比如with(Mockery::type('string'), '.env.test')。
内容的提问来源于stack exchange,提问作者LeonardChallis
相关产品推荐
相关产品推荐

