单元测试 / 函数监视
一个用于phpunit的测试工具,帮助测试全局定义的函数
v1.0.0
2015-02-27 21:53 UTC
Requires
- php: >=5.4.0
Requires (Dev)
- mockery/mockery: 0.9.*
- phpunit/phpunit: ~4.4
This package is not auto-updated.
Last update: 2024-09-14 15:58:10 UTC
README
有时候你想要对全局或本地PHP方法进行单元测试,尤其是在与包含大量全局定义函数的包(如Wordpress)一起工作时。
灵感来源于javascript测试模块:https://github.com/jasmine/jasmine。
安装
composer require --dev unit-testing/function-spy:dev-master
- 或者,在您的
composer.json
中添加模块,如下所示:"require-dev": { "unit-testing/function-spy": "dev-master" }
然后运行composer update
监视器
Spy
类是一个静态容器,它启动一个Registry
实例。它有一个定义的静态方法instance
来实例化或获取绑定实例的Registry
。所有其他静态调用都被转发到Registry
实例。
您只有在尝试模拟要测试的函数或类方法时才需要使用静态方法
<?php namespace MyNamespace;
class TestCase extends \PHPUnit_Framework_TestCase {
use \UnitTesting\FunctionSpy\SpyTrait;
function test_functionOrMethod_CanBeSpied()
{
function_under_test('foo');
$this->assertFunctionLastCalledWith('function_under_test', array('foo'));
$instance = new FakeInstanceThatHasMethodWhichCallsFunctionUnderTest();
$instance->methodWhichCallsFunctionUnderTest('bar');
$this->assertFunctionLastCalledWith('function_under_test', array('bar'));
}
}
function function_under_test()
{
\UnitTesting\FunctionSpy\Spy::function_under_test();
}
class FakeInstanceThatHasMethodWhichCallsFunctionUnderTest {
function methodWhichCallsFunctionUnderTest($param)
{
function_under_test($param);
}
}
注册表
Registry
负责记录所有监视到的函数调用及其相应的参数。它还有一些函数用于执行更深入的分析。
getRecorders
返回一个包含所有被监视函数的数组。数组中的每个键是一个函数名,其值是一个Recorder
实例。getRecorder($name)
获取匹配的函数调用的Recorder
实例或如果没有调用该函数则返回null。flushRecorders
显式清空记录器数组setFunctionResult($name, $result)
为函数创建一个Recoder
实例(如果尚未创建)并设置该函数的返回值- 为了方便,
Registry
实例实现了ArrayAccess
,以便访问/实例化监视器或设置其结果。
记录器
getCalls
获取所有调用及其相应的参数列表wasCalled
检查方法是否被调用wasCalledWith
检查方法是否以特定的参数列表被调用wasLastCalledWith
检查方法的最后一次调用是否与特定的参数列表匹配
SpyTrait
SpyTrait
是一个简单的特质,可以被任何PHPUnit测试用例使用来自动设置和清空Registry
。只需几行代码,它就会实例化Registry
并在测试用例上设置一个$spy
属性,以便在测试中轻松访问。它还扩展了测试用例,添加了一些断言方法来帮助检查全局函数是否被调用。
protected initSpy
:从您的setUp()
方法中调用此方法来初始化监视器和设置$spy
成员protected flushSpy
:从您的tearDown()
方法中调用此方法来清除所有对监视器的调用,以便在每个测试之间清空所有调用。assertFunctionNotCalled
:确保全局函数没有被调用assertFunctionNotCalledWith
:确保全局函数没有以特定参数被调用assertFunctionCalledWith
:确保全局函数以特定参数被调用assertFunctionLastCalledWith:
确保全局函数最近一次以特定参数被调用
注释示例
假设有一个你继承并需要与之工作的方法 doSomethting
。你想要确保它以正确的参数在应该调用的时候被调用。你的类 MyNamespace\MyClass
中有一个方法 doFoo
,它会根据条件调用 doSomething
函数并返回其结果。
测试主题
<?php namespace MyNamespace;
class MyClass {
public function doFoo($param1, $param2)
{
if ($param1 == 'bar')
{
return doSomething($param1, $params);
}
}
}
测试用例
<?php namespace MyNamespace;
class MyTest extends \PHPUnit_Framework_TestCase {
// Use the trait
use \UnitTesting\FunctionSpy\SpyTrait;
protected function setUp()
{
// init the spy
$this->initSpy();
}
protected function tearDown()
{
// flush the spy so we can reset the calls after every test
$this->flushSpy();
}
function test_doFoo_WithBar_CallsDoSomethingWithBar()
{
$myClass = new MyClass();
$myClass->doFoo('bar', 'baz');
// we've ensured that the doSomething() method has been called with bar and baz
$this->assertFunctionLastCalledWith('doSomething', array('bar', 'baz'));
}
function test_doFoo_WithBar_ReturnsResultOfDoSomething()
{
// we'll set the result for the function doSomething() to return "doSomething result"
$this->spy['doSomething']->setResult('doSomething result');
// alternatively, you can also just assign set the property:
// $this->spy['doSomething'] = 'doSomething result';
$myClass = new MyClass();
$result = $myClass->doFoo('bar', 'baz');
// we ensure that the doFoo() method returns the result of doSomething();
$this->assertEquals('doSomething result', $result);
}
function doFoo_WithBaz_NeverCallsDoSomething()
{
$myClass = new MyClass();
$myClass->doFoo('some param which does not call doSomething');
// ensure that doSomething() is never called
$this->assertFunctionNotCalled('doSomething');
}
}
// this is needed because we're overriding the globally defined doSomething within our namespace.
function doSomething()
{
// the Spy static class allows you to simply call any method name and it will log the call with that name.
// if you don't explicity pass parameters, it will attempt to guess the passed parameters to this function
// using debug_backtrace()
return Spy::doSomething();
}
致谢
其他处理此测试问题的包/引用,并作为参考使用