SQL Server Samples 仓库中的 Laravel 示例:Mockery PHP 模拟对象框架使用指南
2026/9/23 14:10:21 网站建设 项目流程

SQL Server Samples 仓库中的 Laravel 示例:Mockery PHP 模拟对象框架使用指南

【免费下载链接】sql-server-samplesAzure Data SQL Samples - Official Microsoft GitHub Repository containing code samples for SQL Server, Azure SQL, Azure Synapse, and Azure SQL Edge项目地址: https://gitcode.com/gh_mirrors/sq/sql-server-samples

Mockery 是一个简洁而灵活的 PHP 模拟对象(mock object)框架,专为 PHPUnit、PHPSpec 等单元测试框架设计。本仓库的 Laravel 示例(samples/development-frameworks/laravel)在composer.jsonrequire-dev中引入了mockery/mockery0.9.*,并将其完整文档随 vendor 目录一并提供(docs/index.rst)。阅读本文后,你将掌握 Mockery 的核心概念、安装方式、Mock 对象创建语法、期望声明(expectation)与参数匹配、PHPUnit 集成等完整技能,可直接在 Laravel 项目的单元测试中落地使用。

Mockery 是什么:面向单元测试的 PHP 模拟对象框架

Mockery 的核心目标是以一套精炼的 API 提供测试替身(test double)能力,用接近人类自然语言的领域特定语言(DSL)清晰定义对象的操作与交互。它被设计为 PHPUnit 自带phpunit-mock-objects的直接替代品,既易于与 PHPUnit 集成,也可以与phpunit-mock-objects共存使用,互不冲突。

在单元测试中,模拟对象用于模拟真实对象的行为,常见用途包括:

  • 提供测试隔离,让被测代码不依赖真实外部依赖;
  • 替身那些尚不存在的对象(例如依赖尚未开发的接口或服务);
  • 在不实现具体代码的前提下,探索式地设计类 API。

模拟对象框架的价值在于:能够灵活生成 Mock 对象与桩(stub),并以可读性极强的 API 设置预期方法调用与返回值,尽可能以接近自然语言的方式捕获真实对象的每一种行为。

在 Laravel 示例中的实际定位

在本仓库的 Laravel 示例(composer.json)中,Mockery 被声明为开发期依赖:

"require-dev": { "fzaninotto/faker": "~1.4", "mockery/mockery": "0.9.*", "phpunit/phpunit": "~4.0", "phpspec/phpspec": "~2.1" }

可见该项目同时使用 PHPUnit 4.x 与 PHPSpec 2.1 作为测试框架,Mockery 作为两者共用的模拟框架被固定为 0.9.x 版本。由于它位于require-dev段,生产环境执行composer install --no-dev时不会安装。这也与本文档所在位置吻合——Mockery 完整文档被打包在 vendor/mockery/mockery/docs 目录下,分为 Getting Started、Reference、Cookbook 三大部分。

安装与引入 Mockery

通过 Composer 安装

首先为项目安装 Composer,然后在composer.jsonrequire-dev中声明依赖。文档建议使用稳定的版本标签(如@stable),也可以直接引用开发分支:

{ "require-dev": { "mockery/mockery": "dev-master" } }

随后执行更新命令即可完成安装:

php composer.phar update

安装后的 Mockery 仅作为开发依赖存在,生产环境执行php composer.phar update --no-dev时不会被安装。本仓库 Laravel 示例的 composer.json 即采用该模式,并锁定为0.9.*版本。

通过 PEAR 安装

Mockery 托管在独立的 PEAR 频道上,可使用如下命令安装(会同时安装 Hamcrest 依赖):

sudo pear channel-discover pear.survivethedeepend.com sudo pear channel-discover hamcrest.googlecode.com/svn/pear sudo pear install --alldeps deepend/Mockery

通过 Git 仓库安装

Mockery 的 master 分支承载开发版本。可以使用 Composer 引用dev-master版本,也可以直接克隆仓库后通过 PEAR 安装。安装过程会同时安装 Mockery 与 Hamcrest——Hamcrest 并非 Mockery 运行的硬性依赖,但强烈建议安装,因为它为参数匹配(argument matching)提供更丰富的匹配器(matcher)能力。

引入自动加载

Mockery 自带自动加载器(autoloader),无需在测试中手动写require_once()。使用时只需确保 Mockery 位于include_path中,并在测试套件的Bootstrap.phpTestHelper.php中注册:

require_once 'Mockery/Loader.php'; require_once 'Hamcrest/Hamcrest.php'; $loader = new \Mockery\Loader; $loader->register();

如果使用 Composer,则只需引入 Composer 生成的自动加载文件即可:

require __DIR__ . '/../vendor/autoload.php'; // 假设 vendor 位于上一级目录

注意:Hamcrest 1.0.0 之前,Hamcrest.php文件名是小写hamcrest.php。升级到 1.0.0 后,请检查所有项目中该文件名是否已更新。

快速上手:第一个 Mockery 测试

假设有一个Temperature类,它通过外部服务采样某地区的温度并计算平均值。数据可能来自 Web 服务或其他数据源,但当前我们并没有这样的服务类。不过,基于Temperature类对服务的调用方式,可以推断出服务类应具备的基本交互:

class Temperature { public function __construct($service) { $this->_service = $service; } public function average() { $total = 0; for ($i=0;$i<3;$i++) { $total += $this->_service->readTemp(); } return $total/3; } }

即便没有真实的服务类,也能清楚看到Temperature对它的预期:readTemp()方法将被调用 3 次。编写测试时,可以用 Mock 对象替代真实服务,从而在无需具体服务实例的情况下验证Temperature的行为:

use \Mockery as m; class TemperatureTest extends PHPUnit_Framework_TestCase { public function tearDown() { m::close(); } public function testGetsAverageTemperatureFromThreeServiceReadings() { $service = m::mock('service'); $service->shouldReceive('readTemp')->times(3)->andReturn(10, 12, 14); $temperature = new Temperature($service); $this->assertEquals(12, $temperature->average()); } }

这段测试的核心逻辑是:通过shouldReceive('readTemp')->times(3)->andReturn(10, 12, 14)声明期望——readTemp必须恰好被调用 3 次,依次返回 10、12、14。Temperature::average()对 3 次读数求和后取平均得到 12,与断言一致。tearDown()中的m::close()负责清理当前测试的 Mockery 容器并执行期望验证;若使用 PHPUnit 集成(见后文),则可以省略该tearDown()

创建 Mock 对象的完整语法

\Mockery::mock()的第一个参数决定 Mock 的类型与行为,第二个参数可以是期望数组或期望闭包(配合期望数组时可为第三参数),下面是文档中列举的全部创建方式。

命名 Mock(最宽松的形式)

$mock = \Mockery::mock('foo');

创建一个名为 "foo" 的 Mock 对象。这里的 "foo" 是名称(不一定是类名),仅作为抛出异常时的简单标识。它生成\Mockery\Mock类型的对象,是所有 Mock 中约束最宽松的形式。

通过期望数组快速设置

$mock = \Mockery::mock(array('foo'=>1,'bar'=>2));

未指定名称,但传入了期望数组——这是快速声明"期望哪些方法、返回什么值"的简便方式。期望数组可以作为第二个参数传给所有形式的mock()

$mock = \Mockery::mock('foo', array('foo'=>1,'bar'=>2));

通过闭包设置可复用期望

$mock = \Mockery::mock('foo', function($mock) { $mock->shouldReceive(method_name); });

除了期望数组,还可以传入包含可复用期望的闭包,作为第二个参数;若与期望数组并用,则作为第三个参数。这是实现可复用 Mock 期望的方式之一。

基于具体类创建 Mock

$mock = \Mockery::mock('stdClass');

当名称是真实类名时,Mock 对象将通过继承获得该类类型,可通过类型提示(type hint)或instanceof校验,适合要求 Mock 必须是特定类型的场景。

基于接口、抽象类创建 Mock

$mock = \Mockery::mock('FooInterface');

任何具体类、抽象类甚至接口都可以作为 Mock 基础,主要目的同样是让 Mock 继承特定类型以通过类型提示。例外是:被标记为final的类或含final方法的类无法被完整 Mock,此时必须使用部分 Mock(partial mock)。

别名 Mock(Alias Mock):模拟静态方法

$mock = \Mockery::mock('alias:MyNamespace\MyClass');

给一个"当前尚未加载"的类名加上alias:前缀,会生成"别名 Mock":为该类名创建指向stdClass的类别名,通常用于模拟公共静态方法。设置在 Mock 对象上、针对静态方法的期望,将作用于该类的所有静态调用。

实例 Mock(Instance Mock / overload)

$mock = \Mockery::mock('overload:MyNamespace\MyClass');

overload:前缀与alias:类似,但区别在于:之后new出来的该类实例会导入在源 Mock($mock)上设置的期望。源 Mock 本身永远不会被验证,它仅作为新实例的期望存储,故称为"实例 Mock"(instance mock),以区别于更简单的"别名 Mock"。

警告:在同一测试中多次使用 alias/instance Mock 会因无法定义同名类而产生致命错误。解决方法是让这类测试各自运行在独立的 PHP 进程中(PHPUnit 与 PHPT 均原生支持)。

同时实现多个接口

$mock = \Mockery::mock('stdClass, MyInterface1, MyInterface2');

第一个参数也可以是用逗号分隔的接口列表,其中最多可包含一个现有类作为基础。类名不要求位于列表首位,但按惯例放在开头更易读。若给定的类不存在,则必须事先定义并包含它,否则会抛出\Mockery\Exception

传统部分 Mock(Partial Mock)

$mock = \Mockery::mock('MyNamespace\MyClass[foo,bar]');

方括号语法告诉 Mockery 对MyNamespace\MyClass进行部分 Mock:仅模拟foo()bar()两个方法,其余方法不被 Mockery 覆盖。这种传统形式适用于任何类或抽象类(例如模拟尚无具体实现的抽象方法)。如果尝试部分 Mock 一个final方法,该实例中会被忽略,final 方法保持原样——因为按 PHP 定义,final 方法本就无法被 Mock。

传递构造函数参数

$mock = \Mockery::mock("MyNamespace\MyClass[foo]", array($arg1, $arg2));

当 Mockery 遇到索引数组作为第二或第三参数时,会将其视为构造函数参数,在构造 Mock 对象时传入。上面的语法创建了一个新的部分 Mock,特别适合bar方法内部通过$this->foo()调用foo的场景。

代理部分 Mock(Proxied Partial Mock)

$mock = \Mockery::mock(new Foo);

向 Mockery 传入任意真实对象会创建"代理部分 Mock"。当真实部分 Mock 不可能实现时(例如 final 类,或必须覆盖 final 方法),此方式非常有用:既然已经能创建具体对象,只需选择性覆盖现有方法的子集(甚至可以添加不存在的非现有方法)来满足期望。

复习:参数约定

所有 Mock 方法都以"要 Mock 的类、对象或别名"作为第一个参数;第二个参数可以是"方法到返回值的期望数组"或"期望闭包"(与期望数组并用时闭包为第三参数)。

\Mockery::self():链式返回自身

\Mockery::self()

当期望中的方法需要返回同一个 Mock 对象时(例如设计 DSL 时——Mockery 自身就是这样的例子),调用\Mockery::self()会返回最近一次通过\Mockery::mock()创建的 Mock 对象:

$mock = \Mockery::mock('BazIterator') ->shouldReceive('next') ->andReturn(\Mockery::self()) ->mock();

以迭代器为例,很多场景下可以把所有迭代元素(往往类型相同)替换为同一个 Mock 对象,让它轮流扮演各个离散元素。

namedMock:按自定义名称生成类

$mock = \Mockery::namedMock('MyClassName', 'DateTime');

namedMock会生成一个以第一个参数为类名的类(如MyClassName),其余参数处理方式与mock相同。例如上述调用创建名为MyClassName、继承DateTime的类。命名 Mock 属于边缘场景,但当代码依赖__CLASS__魔术常量,或需要某个抽象类型的两个不同派生类时,它很有用。

警告:命名 Mock 只能创建一次,后续以不同参数再次调用namedMock很可能引发异常。

行为修饰符:改变 Mock 的默认行为

shouldIgnoreMissing():被动 Mock

\Mockery::mock('MyClass')->shouldIgnoreMissing()

该修饰符将 Mock 标记为"被动 Mock"(Passive Mock):调用未被期望覆盖的方法时,返回null,而不是通常那样抱怨"没有匹配该调用的期望"。若希望恢复 0.7.2 时代的行为——返回\Mockery\Undefined类型的对象(即空对象),可叠加:

\Mockery::mock('MyClass')->shouldIgnoreMissing()->asUndefined()

返回的空对象只是一个占位符,如果被误用在不该出现的地方,通常无法通过逻辑检查。

makePartial() / shouldDeferMissing():被动部分 Mock

\Mockery::mock('MyClass')->makePartial()
\Mockery::mock('MyClass')->shouldDeferMissing()

这两种写法等价,称为"被动部分 Mock"(Passive Partial Mock,区别于后文讨论的真实部分 Mock 对象)。它对未受期望约束的所有方法,会委托给 Mock 的父类(即MyClass)执行。与前面shouldIgnoreMissing()返回null不同,此行为会直接调用父类的对应方法。

期望声明(Expectation Declarations):定义 Mock 的行为与调用方式

创建 Mock 对象后,下一步就是通过期望声明定义它的行为与调用约束。

声明期望的方法

shouldReceive(method_name)

声明 Mock 期望收到对指定方法的调用,这是所有后续期望与约束的起点。

shouldReceive(method1, method2, ...)

一次声明多个期望方法,所有方法共享后续链式期望或约束。

shouldReceive(array('method1'=>1, 'method2'=>2, ...))

声明多个期望调用并同时指定返回值的数组形式。

shouldReceive(closure)

仅从部分 Mock 创建:生成"Mock 对象记录器"(recorder),它是原始对象的简单代理,闭包可对其执行一系列操作,这些操作被记录为部分 Mock 上的期望。典型场景是在重构时基于已有用法自动录制期望。

shouldNotReceive(method_name)

声明 Mock 不应收到对指定方法的调用,等价于shouldReceive()->never()

参数约束

with(arg1, arg2, ...) / withArgs(array(arg1, arg2, ...))

为该期望增加"参数列表必须匹配"的约束。可以借助内置匹配器大幅增强灵活性,例如\Mockery::any()匹配该位置的任意参数;Mockery 也允许使用 Hamcrest 匹配器(如 Hamcrest 的anything()等价于\Mockery::any())。这意味着同一方法可依据不同参数设置不同期望——期望只在参数完全匹配时才生效。

withAnyArgs()

声明该期望匹配任何参数的方法调用(未特别指定时是默认行为)。

withNoArgs()

声明该期望只匹配零参数的方法调用。

返回值设置

andReturn(value)

设置期望方法调用的返回值。

andReturn(value1, value2, ...)

设置返回值序列或闭包序列:第一次调用返回 value1,第二次返回 value2。注意:之后对该 Mock 方法的所有调用,都始终返回最后(或唯一)给定的值。

andReturnNull() / andReturn([NULL])

两种写法主要是向测试读者传达"该方法返回 null 或什么都不返回"。

andReturnValues(array)

andReturn()的替代语法,接受数组而非参数列表。返回顺序由数组数字索引决定,先前返回值耗尽后,后续调用返回最后一个数组成员。

andReturnUsing(closure, ...)

设置一个闭包,用传入方法的参数调用它,并将闭包返回值作为结果返回。适合对参数做动态加工后得到相关结果;闭包可通过额外参数排队,用法同andReturn()

注意:当前不能混用andReturnUsing()andReturn()

andThrow(Exception)

声明该方法被调用时抛出给定的Exception对象。

andThrow(exception_name, message)

也可以不传对象,而传异常类名与消息,由 Mock 方法抛出新异常。

andSet(name, value1) / set(name, value1)

配合期望使用:当匹配的方法被调用时,同时将 Mock 对象的公共属性设置为指定值。

passthru()

让期望绕过返回值队列,转而调用被 Mock 类的真实方法并返回结果。本质上,它允许对真实方法施加期望匹配与调用次数验证,同时仍然以期望的参数调用真实类方法。

调用次数约束

zeroOrMoreTimes()

声明期望方法可被调用零次或多次(所有方法未另行指定时的默认行为)。

once()

声明方法只能被调用一次。与所有调用次数约束一样,违反时会抛出\Mockery\CountValidator\Exception,并可被atLeast()atMost()修改。

twice()

声明方法只能被调用两次。

times(n)

声明方法只能被调用 n 次。

never()

声明方法绝不能被调用——永远!

atLeast()

为下一个调用次数期望添加最小值修饰,atLeast()->times(3)表示调用必须至少 3 次。

atMost()

添加最大值修饰,atMost()->times(3)表示调用不得超过 3 次,也允许零次调用。

between(min, max)

设置调用次数的区间,等价于atLeast()->times(min)->atMost()->times(max)的简写;可跟一个无参的times()以保持 API 的自然语言可读性。

调用顺序约束

ordered()

声明该方法必须在与同样标记的方法之间按特定顺序被调用,顺序由设置期望时使用该修饰符的顺序决定。

ordered(group)

将方法声明为某个顺序组(可命名或编号)的成员。组内方法可任意顺序调用,但组外有序调用相对该组是有序的——例如可设置 method1 在 group1 之前、group1 在 method2 之前。

globally()

ordered()ordered(group)之前调用,声明该顺序约束作用于所有 Mock 对象(而非仅当前 Mock),从而跨多个 Mock 规定调用顺序。

默认期望与链式取回

byDefault()

将期望标记为默认期望。默认期望在未创建非默认期望时生效,后创建的非默认期望会立即替换先前定义的默认值。这样可以在setup()中设置默认 Mock,再在具体测试中按需微调。

getMock()

从期望链中返回当前 Mock 对象,便于将 Mock 设置保持为单条语句:

$mock = \Mockery::mock('foo')->shouldReceive('foo')->andReturn(1)->getMock();

参数匹配与验证(Argument Validation)

with()中传入的参数决定了"调用如何匹配期望"。可以为同一方法设置多个期望,各自按参数区分。匹配采用"最佳匹配"(best fit)原则:显式匹配优先于泛化匹配。

显式匹配指期望参数与实际参数容易判定相等(=====);更泛化的匹配可通过正则表达式、类提示(class hinting)与内置匹配器实现。Mockery 内置匹配器并未覆盖所有可能,但提供对 Hamcrest 匹配器库的可选支持(Hamcrest 是 Java 同名库的 PHP 移植版,同时也有 Python、Erlang 等版本)。由于 Hamcrest 已提供出色的自然语言 DSL 工具集,Mockery 没有必要重复造轮子。

内置匹配器一览

with(1)

匹配整数1,通过===(全等)判定;也允许较宽松的==(等于)判定,此时字符串'1'也能匹配该参数。

with(\Mockery::any()) OR with(anything())

匹配任意参数(anything()为 Hamcrest 等价写法)。

with(\Mockery::type('resource')) OR with(resourceValue()) OR with(typeOf('resource'))

匹配任意资源类型,即is_resource()返回 true。Type 匹配器接受任意可拼成is_前缀的有效类型检查字符串,例如\Mockery::type('float')对应is_float()检查,\Mockery::type('callable')对应is_callable()检查。Type 匹配器也接受类名或接口名,用于对实际参数做instanceof判定(Hamcrest 对应anInstanceOf())。

with(\Mockery::on(closure))

On 匹配器接受一个闭包,实际参数会被传入其中;闭包返回布尔true即视为匹配。当参数期望过于复杂、超出默认匹配器能力时,此方法价值极大。Hamcrest 无对应实现。

with('/^foo/') OR with(matchesPattern('/^foo/'))

参数声明器也假定任意字符串可能是正则表达式。正则匹配仅在两种情况同时满足时启用:a) 不存在=====匹配;b) 该字符串被验证为合法正则(即preg_match()不返回 false)。若不喜欢隐式正则检测,Hamcrest 提供更显式的matchesPattern()函数。

with(\Mockery::ducktype('foo', 'bar'))

Ducktype 匹配器是类类型匹配的替代方案:匹配任何"包含给定方法列表"的对象(即该对象可调用foobar方法)。Hamcrest 无对应实现。

with(\Mockery::mustBe(2)) OR with(identicalTo(2))

MustBe 匹配器比默认匹配器更严格:默认匹配器允许 PHP 类型转换(字符串'2'可匹配整数 2),而 MustBe 要求参数与期望值类型相同——同一场景下'2'(字符串)匹配整数 2 会被 MustBe 判定失败。注意:该匹配器对对象不做全等比较,因为 PHP 要求两个对象为同一实例才全等;当对象在返回前才生成时,全等匹配几乎不可能成立。

with(\Mockery::not(2)) OR with(not(2))

Not 匹配器匹配任何"不等于或不全等于"其参数的值。

with(\Mockery::anyOf(1, 2)) OR with(anyOf(1,2))

匹配等于给定参数中任意一个的值。

with(\Mockery::notAnyOf(1, 2))

匹配不等于也不全等于给定参数中任何一个的值。Hamcrest 无对应实现。

with(\Mockery::subset(array(0 => 'foo')))

匹配任何"包含给定数组子集"的数组,同时比较键名与键值。Hamcrest 无对应实现,但它可以用hasEntry()hasKeyValuePair()检查单条条目。

with(\Mockery::contains(value1, value2))

匹配任何"包含所列值"的数组,忽略键名。

with(\Mockery::hasKey(key));

匹配任何"包含给定键名"的数组。

with(\Mockery::hasValue(value));

匹配任何"包含给定值"的数组。

与 PHPUnit 集成

Mockery 是设计为简单易用的独立模拟框架,与测试框架的集成完全可选。最基本的集成方式是在测试中定义tearDown()并调用:

public function tearDown() { \Mockery::close(); }

该静态调用会清理当前测试使用的 Mockery 容器,并执行期望所需的验证任务。为书写简便,可用更短的别名:

use \Mockery as m; class SimpleTest extends PHPUnit_Framework_TestCase { public function testSimpleMock() { $mock = m::mock('simplemock'); $mock->shouldReceive('foo')->with(5, m::any())->once()->andReturn(10); $this->assertEquals(10, $mock->foo(5)); } public function tearDown() { m::close(); } }

自动清理:TestListener

若要避免手动调用 close 方法,并让 Mockery 从代码覆盖率报告中移除自身,可在测试套件中注册 Mockery 的 PHPUnit 监听器:

// 创建套件 $suite = new PHPUnit_Framework_TestSuite(); // 创建结果监听器并添加 $result = new PHPUnit_Framework_TestResult(); $result->addListener(new \Mockery\Adapter\Phpunit\TestListener()); // 运行测试 $suite->run($result);

若使用 PHPUnit 的 XML 配置方式,可在配置中加入:

<listeners> <listener class="\Mockery\Adapter\Phpunit\TestListener"></listener> </listeners>

务必确保 Composer 或 Mockery 的自动加载器已出现在 bootstrap 文件中,否则还需为该TestListener类定义file属性指向其所在文件。

进程隔离的注意事项

PHPUnit 支持让测试在独立进程中运行以获得更好的隔离性。Mockery 通过Mockery::close()验证期望,其 PHPUnit 监听器会在每个测试后自动调用该方法。但使用进程隔离时,该监听器不会在正确的进程中执行,导致期望可能未被验证,且不会抛出任何Mockery\Exception。因此在使用进程隔离时,不能依赖 Mockery 自带的 PHPUnitTestListener,必须在tearDown()中显式调用Mockery::close()(即本文前述最基础的方式)。

升级注意事项

文档记录了 0.8 与 0.9 两个版本的关键行为变更,如果你在 Laravel 示例中升级mockery/mockery版本(当前锁定 0.9.*),需要注意:

  • 升级到 0.9:Mockery 的生成器(generator)被完全重写,任何与 Mockery 深度集成的代码都需要重新评估。
  • 升级到 0.8shouldIgnoreMissing()行为变化——0.7.2 及更早版本中,未匹配已知期望的方法调用返回\Mockery\Undefined实例;自 0.8.0 起改为返回null。可显式恢复旧行为:
$mock = \Mockery::mock('stdClass')->shouldIgnoreMissing()->asUndefined();

深入阅读:更多参考文档与 Cookbook

本仓库随包提供了完整的 Mockery 文档集(docs),除本文覆盖的内容外,还可按需查阅:

  • 快速参考:reference/startup_methods.rst(Mock 创建与行为修饰符全解)
  • 期望声明:reference/expectations.rst
  • 参数匹配:reference/argument_validation.rst
  • PHPUnit 集成:reference/phpunit_integration.rst
  • 部分 Mock:reference/partial_mocks.rst
  • 公共属性 / 静态属性:reference/public_properties.rst、reference/public_static_properties.rst
  • 引用传递行为:reference/pass_by_reference_behaviours.rst
  • Demeter 链:reference/demeter_chains.rst
  • 对象录制:reference/object_recording.rst
  • final 类与 final 方法:reference/final_methods_classes.rst
  • 魔术方法:reference/magic_methods.rst
  • 配置 / 异常 / 保留方法名 / 易错点:reference/mockery/configuration.rst、reference/mockery/exceptions.rst、reference/mockery/reserved_method_names.rst、reference/mockery/gotchas.rst
  • Cookbook 技巧:cookbook/index.rst(含默认期望、Mock 对象检测、硬依赖 Mock 等实战技巧,见 cookbook 目录)

在 Laravel 项目的单元测试实践中,建议以 PHPUnit 的tearDown()显式调用Mockery::close()作为稳健基线,再按需引入 TestListener 简化写法;使用shouldReceive系列声明期望、配合参数匹配器精确控制调用约束,即可获得与自然语言高度一致、可读且可维护的测试代码。

【免费下载链接】sql-server-samplesAzure Data SQL Samples - Official Microsoft GitHub Repository containing code samples for SQL Server, Azure SQL, Azure Synapse, and Azure SQL Edge项目地址: https://gitcode.com/gh_mirrors/sq/sql-server-samples

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询