hafriedlander / phockito
受Java Mockito启发的PHP Mocking框架
This package is not auto-updated.
Last update: 2024-09-09 11:23:42 UTC
README
受Java Mockito启发的Mocking框架
访问 原始网站 了解API背后的哲学和更多示例(但请注意,这目前只是一个部分实现)
感谢Mockito的开发者带来的灵感,以及hamcrest-php使得这一切变得简单。
示例Mocking
// Create the mock $iterator = Phockito::mock('ArrayIterator'); // Use the mock object - doesn't do anything, functions return null $iterator->append('Test'); $iterator->asort(); // Selectively verify execution Phockito::verify($iterator)->append('Test'); // 1 is default - can also do 2, 3 for exact numbers, or 1+ for at least one, or 0 for never Phockito::verify($iterator, 1)->asort();
如果PHPUnit可用,在失败时验证抛出PHPUnit_Framework_AssertionFailedError
(看起来像断言失败),否则只抛出Exception
示例Stubbing
// Create the mock $iterator = Phockito::mock('ArrayIterator'); // Stub in a value Phockito::when($iterator->offsetGet(0))->return('first'); // Prints "first" print_r($iterator->offsetGet(0)); // Prints null, because get(999) not stubbed print_r($iterator->offsetGet(999));
替代API,jsMockito风格
// Stub in a value Phockito::when($iterator)->offsetGet(0)->return('first');
Spies
Mock是完整的Mock - 对未Stub的函数的方法调用总是返回null,并且从不调用父函数。
您还可以通过调用spy
而不是mock
来创建部分Mock。在Spies中,对未Stub的函数的方法调用将调用父函数。
由于Spies是正确的子类,这允许您在类中调用其他方法时进行Stub
class A { function Foo(){ return 'Foo'; } function Bar(){ return $this->Foo() . 'Bar'; } } // Create a mock $mock = Phockito::mock('A'); print_r($mock->Foo()); // 'null' print_r($mock->Bar()); // 'null' // Create a spy $spy = Phockito::spy('A'); print_r($spy->Foo()); // 'Foo' print_r($spy->Bar()); // 'FooBar' // Stub a method Phockito::when($spy)->Foo()->return('Zap'); print_r($spy->Foo()); // 'Zap' print_r($spy->Bar()); // 'ZapBar'
参数匹配
Phockito允许在任意参数上使用Hamcrest匹配器。Hamcrest是一个包含“匹配函数”的库,给定一个值,如果该值匹配某些规则,则返回true。
Hamcrest匹配器默认不包含,因此第一步是在包含Phockito后立即调用Phockito::include_hamcrest();
。注意,这将导入Hamcrest匹配器为全局函数 - 通过将false作为参数传递,可以通过使所有匹配器仅作为Hamcrest
的静态方法(以牺牲更糟的测试代码外观为代价)来保持命名空间清洁。
包含后,您可以将Hamcrest匹配器作为when或verify规则中的参数传递,例如
class A { function Foo($a){ } } $stub = Phockito::mock('A'); Phockito::when($stub)->Foo(anything())->return('Zap');
一些常见的Hamcrest匹配器
- 核心
anything
- 总是匹配,如果您不关心被测试的对象是什么,则很有用
- 逻辑
allOf
- 如果所有匹配器都匹配,则匹配,短路(类似于PHP &&)anyOf
- 如果任何匹配器匹配,则匹配,短路(类似于PHP ||)not
- 如果包装的匹配器不匹配,则匹配,反之亦然
- 对象
equalTo
- 使用==运算符测试对象相等性anInstanceOf
- 测试类型notNullValue
,nullValue
- 测试null
- 数字
closeTo
- 测试浮点值接近给定的值greaterThan
,greaterThanOrEqualTo
,lessThan
,lessThanOrEqualTo
- 测试排序
- 文本
equalToIgnoringCase
- 测试字符串不区分大小写的相等性equalToIgnoringWhiteSpace
- 测试字符串相等性时忽略空白差异containsString
,endsWith
,startsWith
- 测试字符串匹配
与Mockito的不同之处
Stubbing方法更灵活
在Mockito中,构建Stub时使用的方法限于thenReturns,thenThrows。在Phockito中,只要方法中有'return'或'throw',就可以使用任何方法,因此Phockito::when(...)->return(1)->thenReturn(2)
是可行的。
类型安全的参数匹配
在Mockito中,为了使用Hamcrest匹配器,使用argThat
方法来满足类型检查器。在PHP中,需要一些额外的帮助。Phockito提供了argOfTypeThat
,用于提供Hamcrest匹配器的类型提示参数。
class A { function Foo(B $b){ } } class B {} $stub = Phockito::mock('A'); $b = new B(); Phockito::when($stub)->Foo(argOfTypeThat('B', is(equalTo($b))))->return('Zap');
还可以将模拟对象传递给 'when',而不是传递模拟对象上方法调用的结果,例如 Phockito::when($mock)->methodToStub(...)->thenReturn(...)
。这完全绕过了类型系统。
注意,argOfTypeThat
只与对象类型提示兼容;具有 array
或 callable
类型提示的参数无法以类型安全的方式处理。
验证 'times' 参数已更改
在 Mockito 中,验证时使用的 'times' 参数是接口 VerificationMode 的对象(如 times、atLeastOnce 等函数返回的对象)。
目前我们只接受一个整数,或者一个整数后面跟着 '+'。它不具有可扩展性。
回调代替答案
在 Mockito 中,您可以通过调用 thenAnswer 并传递一个具有特定方法的对象的实例来从模拟方法返回动态结果。在 Phockito 中,您可以通过传递 callback
参数并使用 thenCallback 来调用它,该回调将使用模拟方法被调用时传递的参数来调用。
默认参数
PHP 有默认参数,与 Java 不同。如果您在模拟或验证匹配器中未指定默认参数,它将匹配默认参数。
class Foo { function Bar($a, $b = 2){ /* NOP */ } } // Create the mock $mock = Phockito::mock('Foo'); // Set up a stub Phockito::when($mock->Bar(1))->return('A'); $mock->Bar(1); // Returns 'A' $mock->Bar(1, 2); // Also returns 'A' $mock->Bar(1, 3); // Returns null, since no stubbed return value matches
返回类型
Mockito 根据声明的返回类型返回一个类型兼容的 false。我们没有在 PHP 中定义类型值,所以我们始终返回 null。TODO:支持使用 phpdoc @return 声明。
TODO
- Mockito 特定的 hamcrest 匹配器(anyString 等)
- 按顺序验证
许可
版权 (C) 2012 Hamish Friedlander / SilverStripe。
可以在您的选择下,在与 SilverStripe 相同的许可证或 Apache Public License V2(https://apache.ac.cn/licenses/LICENSE2.0.html)下分发
您不需要做任何特别的事情来选择其中一个许可证,也不需要通知任何人您使用的是哪个许可证。
Hamcrest-php 在其自己的许可证下 - 查看 hamcrest-php/LICENSE.txt。