ernestmarcinko / mockutils
PHPUnit 测试模拟工具
1.0.3
2024-03-28 11:52 UTC
Requires
- php: ^8.3
- php-mock/php-mock: ^2.5
- phpunit/phpunit: 11.*
Requires (Dev)
- phpstan/phpstan: ^1.10
- squizlabs/php_codesniffer: ^3.8
This package is auto-updated.
Last update: 2024-09-28 13:21:03 UTC
README
本包通过 MockUtils
特性为 PHPUnit 的 TestCase 类(及其子类)提供了一些实用函数
- 全局模拟 -
setGlobalMocks()
和unsetGlobalMocks()
方法用于设置命名空间内的全局函数模拟 - 异常断言 - 通过
expectCatchException()
- 与expectException()
方法类似,但不会终止测试执行
安装与包含
要安装此包
composer require ernestmarcinko/mockutils --dev
在你的测试中包含
有两种方法,一种是通过特性扩展你的 TestCase 功能(推荐)
use ErnestMarcinko\MockUtils\MockUtils; use PHPUnit\Framework\TestCase; class MyTest extends TestCase { use MockUtils; ... }
..或者使用 MockUtilsTestCase 类代替 TestCase
use ErnestMarcinko\MockUtils\MockUtilsTestCase; class MyTest extends MockUtilsTestCase { ... }
MockUtilsTestCase
只是一个扩展了 TestCase
并使用了 MockUtils
的空类。
全局模拟
特性为 setGlobalMocks()
和 unsetGlobalMocks()
方法添加了两个实用函数,用于设置和取消全局模拟。
setGlobalMocks
protected function setGlobalMocks(array $global_mocks, ?string $namespace): void
将全局模拟设置为给定的命名空间。
参数
示例
假设你有一个服务,它使用 curl_exec
从 API 获取响应。在测试中,你想模拟它,避免实际连接到 API,而是使用预定义的响应进行测试。
namespace MyNamespace\MySubNamespace; class MyClass { public function handler() { //.... $response = curl_exec($curl); // you want to mock this //You do something with $response below } }
在测试中,我们需要 curl_exec 返回 'response' 作为模拟,为此
namespace MyTestNamespace; class TestMyClass { public function testHandler() { $this->setGlobalMocks( [ 'curl_exec' => 'response' ], 'MyNamespace\\MySubNamespace' ) $o = new MyClass(); $this->assertSame( 'expected output', $o->handler() ); } }
也可以定义一个可调用对象而不是静态响应
namespace MyTestNamespace; class TestMyClass { public function testHandler() { $this->setGlobalMocks( [ 'curl_exec' => function($curl) { return 'response'; } ], 'MyNamespace\\MySubNamespace' ) $o = new MyClass(); $this->assertSame( 'expected output', $o->handler() ); } }
unsetGlobalMocks
protected function unsetGlobalMocks(?array $global_mocks=null): void
取消给定全局模拟或之前定义的所有全局模拟。
参数
示例
namespace MyTestNamespace; class TestMyClass { public function testHandler() { $this->setGlobalMocks( [ 'time' => fn()=>time()-3600, 'json_decode' => array(), 'strval' => fn($v)=>$v, ], 'MyNamespace\\MySubNamespace' ) $o = new MyClass(); $this->assertSame( 'expected output 1', $o->handler() ); $this->unsetGlobalMocks(array('time')); // unset just the time mock $this->assertSame( 'expected output 2', $o->handler() ); $this->unsetGlobalMocks(); // unset all remaining mocks $this->assertSame( 'expected output 3', $o->handler() ); } }
异常断言
expectCatchException
检查是否抛出了异常 而不终止 执行。
protected function expectCatchException(callable $fn, string $throwable, ?string $message = null): void
与 PHPUnit 核心库的 TestCase::expectException
相比,此函数不会终止测试执行。但是,必须将测试函数传递为一个闭包,例如: expectCatchException(fn()=>$o->myMethod(), ...)
参数
返回值
此函数为空,不返回任何内容
expectCatchException
如果没有抛出异常或未满足任何条件,将触发TestCase::fail()
示例
namespace MyTestNamespace; class TestMyClass { public function testHandler() { $this->expectCatchException(function(){ throw new Exception('hey!'); }, Exception::class); // Execution continues $this->expectCatchException(function(){ throw new Exception('hey!'); }, Exception::class, 'hey!'); $o = new MyClass(); $this->expectCatchException(fn()=>$o->handle(), Exception::class); $this->expectCatchException( fn()=>$o->handle(), Exception::class, 'Exception message!' ); } }