superreal / srunit
包含专门用于编写OXID模块单元测试环境的库。
Requires
- fzaninotto/faker: v1.4.0
- hamcrest/hamcrest-php: 1.2.0
- mikey179/vfsstream: v1.2.0
- mockery/mockery: 0.9.0
- phpunit/phpunit: 4.1.1
Suggests
- jenswiese/phpunit-helpers: dev-master
- superreal/srunit-oxid-module: 0.9.*@dev
This package is not auto-updated.
Last update: 2024-09-14 15:47:28 UTC
README
本包包含编写oxid模块单元测试所需的所有必要组件 - 包括启动和模拟功能。
安装
只需将以下要求添加到您的项目composer.json
文件中,然后调用composer update superreal/srunit
"superreal/srunit": "0.10.*@dev"
所有必需的包将自动安装(例如PHPUnit,Mockery)。
为模块设置单元测试
以下步骤是设置您的模块单元测试所需的。
模块配置
将phpunit.xml添加到模块根目录,至少包含以下内容
<phpunit bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="Module Tests">
<directory>tests</directory>
</testsuite>
</testsuites>
<listeners>
<listener class='SrUnit\Adapter\Phpunit\TestListener' />
</listeners>
</phpunit>
项目/商店配置
将phpunit.xml添加到商店根目录,包含以下内容
<phpunit bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="Project Tests">
<directory>tests</directory>
</testsuite>
<testsuite name="Module Tests">
<directory>modules</directory>
</testsuite>
</testsuites>
<listeners>
<listener class='SrUnit\Adapter\Phpunit\TestListener' />
</listeners>
</phpunit>
完成上述步骤后,您可以从商店根目录运行phpunit,所有测试都将执行(项目和相关模块)。
注意:添加TestListener
的效果是,在每个测试后都会验证预期。
启动
您的测试应放置在tests
目录下。在tests目录下放置您的bootstrap.php
,内容如下
\SrUnit\Bootstrap::create(__DIR__)->bootstrap();
启动过程将自动检索所有必需的目录,并加载composer自动加载器
,以及基于您的metadata.php
配置的OXID模块类的自定义自动加载器
。
这也适用于您从商店根目录运行测试的情况。在这种情况下,启动过程将设置所有测试的自动加载,包括模块内的测试。但这是基于您模块的正确配置。这意味着:模块负责正确设置自动加载。
这首先是通过在您的composer.json
中添加“autoload”配置来完成的。如果您需要为Namespace定义多个目录(例如,为测试),您必须在那里做。除了这些,metadata.php
也被考虑在内。在"extend"
和/或"files"
部分。
测试用例必须继承自SrUnit\TestCase
您所有的测试用例都应该继承自SrUnit\TestCase,以便启用OXID相关功能或方便方法。
加载OXID
OXID默认不加载。基本功能,如oxNew()
或oxDb::getDb()
被模拟。您可以通过使用模拟来控制它们的行为。
如果您需要加载OXID(例如,进行集成测试),您可以通过添加组注解来加载OXID
@group needs-oxid
TestListener
将激活特定测试的OXID加载,并启用/禁用所需的模块superreal/srunit-module
。该模块也必须在您的composer.json
中要求 - 否则测试将因异常而终止。
运行phpunit
当您设置好环境,如前所述,您可以在商店根目录或特定模块中运行phpunit
。但为了正确设置自动加载,您需要运行随composer提供的phpunit。根据您的设置,您可以使用以下调用
bin/phpunit
vendor/bin/phpunit
使用Mock-Factory
Factory支持您创建模拟来替换SUT的依赖项。它还通过易于理解的流畅接口处理OXID相关的要求。
当您在方法链的末尾调用getMock()方法时,您将获得带有少量附加功能的Mockery\MockInterface(例如,实现ArrayAccess())。
底层库是Mockery,即使它没有被直接调用,你也会从Mockery中得到Mock对象。
创建简单Mock
简单Mock,简单调用
$mock = Factory::create('TestClass')->getMock();
之后,你可以通过简单地使用Mockery方法来定义Mock的行为
$mock->shouldReceive('getParam')->andReturn('a-value')
测试OXID扩展
当涉及到扩展OXID核心类(例如oxArticle)时,你可能需要测试你的实现是否正确。如果你不需要整个OXID堆栈来测试你的实现,你可以通过这样做来Mock仅仅是_parent
类
$mock = Factory::createParentClass('\SrMyExtensionOxArticle_parent')->getMock();
请注意,这个调用实际上会定义一个名为SrMyExtensionOxArticle_parent
的类,并应用你将在其上应用的行为。
这意味着:在初始实例化之后,该类在整个PHP过程中将具有相同的行为。每次你创建一个新的实例,你都会得到相同的结果。当你需要为不同的测试提供不同的行为时,你必须通过添加以下注解来独立运行你的测试
/**
* @runInSeparateProcess
*/
public function testInSeparateProcess()
{
// ...
}
使用OXID-Factory的集成测试
如果你需要测试你模块的集成,或者你想使用OXID工厂以便拥有整个堆栈可用,你可以使用以下调用
$mock = Factory::create('\oxArticle')
->registerForOxNew()
->getMock();
这个调用将创建一个Mock,并将这个Mock对象注册到每次调用oxNew('oxArticle')
时可以检索。当你有依赖于经常使用oxNew()调用的类时,这非常有用,并且你无法从外部更改此行为。
提供的Mock
通常,你不想创建Mock,并且反复应用相同的行为。对于这种情况,你可以使用提供程序来获取具有默认值/存根的Mock。
$mock = Factory::create('\oxArticle')
->useProvisioning()
->getMock();
在某些情况下,这个调用将导致异常,因为没有提供程序可用。然后你需要自己实现一个提供程序。
具有接口的Mock
你可以定义Mock应该实现的接口,如下所示
$mock = Factory::create('TestClass')
->implementsInterface('\Iterator')
->implementsInterface('\Mockable')
->getMock();
请注意:接口必须存在!
对于某些Iterator接口,已经启用了特定方法的存根机制
- Iterator
- ArrayAccess
对于这些接口,需要向方法传递数据,才能获得期望的行为
$data = array('foo', 'bar', 'barz');
$mock = Factory::create('TestClass')
->implementsInterface('\Iterator', $data)
->getMock();
当你使用这个Mock时,你会遍历给定数据。
Mock文件系统
如果你的系统依赖文件系统,并且你想设置特定的测试环境,你可以使用文件系统实用程序。
创建文件系统
你可以选择使用虚拟文件系统或物理文件系统。虽然虚拟文件系统适用于大多数情况,但有时需要使用物理文件系统(例如,如果你正在处理符号链接)。
(虚拟文件系统是通过vfsStream实现的)
$fs = new VirtualFilesystem($rootDir);
或
$fs = new Filesystem($rootDir);
通过使用TestCase::createFilesystem()
在你的TestCase
中,你可以调用createFilesystem()
方法。你可以通过传递第二个参数来选择虚拟文件系统或物理文件系统。无论如何,用法都是相同的。
$fs = $this->createFilesystem('/tmp', FilesystemInterface::VIRTUAL);
或
$fs = $this->createFilesystem('/tmp', FilesystemInterface::PHYSICAL);
信息:即使你选择物理文件系统并将/tmp
定义为根目录,创建的环境也不会写入系统临时目录/tmp
。
创建目录和文件
你会得到一个实现了FilesystemInterface
的对象
createDirectory()
createFile()
tearDown()
你可以使用完整的路径创建目录和文件。
$filesystem->createDirectory('path/to/diretory');
$filesystem->createFile('path/to/file.txt');
然后你会得到一个你可以与之工作的SplFileInfo
对象。
清理环境
为了控制测试的清理过程,你需要调用tearDown()
方法(例如,在你的TestCase
的tearDown()
方法中)。
protected function tearDown()
{
$this->filesystem->tearDown();
}
实际上,这仅在你使用物理文件系统时才需要,因为虚拟文件系统只存在于内存中,并且会自动删除。但为了保持一致性:坚持这种方法。