hafriedlander/phockito

受Java Mockito启发的PHP Mocking框架

1.0.0 2013-08-15 23:44 UTC

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 - 测试类型
    • notNullValuenullValue - 测试null
  • 数字
    • closeTo - 测试浮点值接近给定的值
    • greaterThangreaterThanOrEqualTolessThanlessThanOrEqualTo - 测试排序
  • 文本
    • equalToIgnoringCase - 测试字符串不区分大小写的相等性
    • equalToIgnoringWhiteSpace - 测试字符串相等性时忽略空白差异
    • containsStringendsWithstartsWith - 测试字符串匹配

与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 只与对象类型提示兼容;具有 arraycallable 类型提示的参数无法以类型安全的方式处理。

验证 '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。