genesis / phpunitassister
扩展phpunit WebTestCase类,以提供更简单的模拟和断言(链式模拟和链式断言)
Requires
- php: >=5.3.0
- phpunit/phpunit: >=3.7.0
README
本README通常会记录启动应用程序所需的任何步骤。
这个仓库是做什么的?
- 快速总结:PHPUnit辅助程序的主要目标是最大限度地减少测试中编写的重复代码量。初始版本专注于模拟和断言方法。
我该如何设置?
安装/克隆仓库
使用composer
{
"require": {
"genesis/phpunitassister": "1.0.*"
}
}
PHPUnit辅助程序是一个简单的类库,应将其作为实际测试类的父类。
配置:没有太多需要配置的,mockProvider.php是一个自定义文件,您可以在此处定义您的应用程序的模拟类。目前它适用于symfony2应用程序。
- 依赖项:PHPUnit
- 数据库配置:没有数据库调用。
- 如何运行测试:只需将对象处理类扩展到您的测试类中,并运行应用程序,它应该可以正常工作,即使使用纯PHPUnit方法编写。一旦工作正常,请使用提供的方法。
// YourProject/Src/Bundle/Test/YourTestClass.Test.php
use PHPUnitAssister\Core\TestObjectHandler;
class YourTestClass extends TestObjectHandler {
public function testYourMethod()
{
...
}
}
您还可以选择扩展辅助程序以包含您自己的自定义方法,已经提供了一个作为扩展类的基symfony2模拟提供程序。
// PHPUnitAssister/Src/Extensions/Symfony2MockProvider.Class.php
namespace PHPUnitAssister\Extensions;
use PHPUnitAssister\Core\TestObjectHandler;
/*
* This class provides standard symfony2.3 mock objects
*/
class Symfony2MockProvider extends Mocker{
...
}
// YourClass/ExtendedMockProvider.Class.php
class ExtendedMockProvider extends Mocker{ // or Symfony2MockProvider
}
贡献指南
- 欢迎对此小型项目做出贡献。
我应该和谁联系?
仓库所有者或管理员
phpunitAssister缩写调用
// YourProject/Src/Bundle/Test/YourTestClass.Test.php
// 设置测试对象 $this->setTestObject($yourClassToTest, array $arguments);
// 模拟 $this->setmo(object $mocked) // 设置模拟对象
->mm($method, array $args ...) // mock method
->mmx(array $methods, array $options) // Mock multiple methods at once, stops chaining
->then($method, array $args ...) // Chain next mock object with previous will clause object
->getmo() // get mock object
->getmos() // get mock objects
->setbm() // Set base mock
// 断言 $this->tm($method) // 测试方法
->with($param1, $param2) // params for the test method
// Basic assertions
->assert('true') // Assert that result is true
->assert('true', 'your result') // Assert that result equals the string 'your result'
->assert('false')
->assert('equals', 'something-that-equals-result') // Perform equal assertion
->assert('empty') // assert if result is empty
->assert('notempty') // assert if result in non-empty
// String position
->assert('contains', 'This-would-be-something-you-expect-the-result-to-contain')
->assert('true', '!==something-not-equal-to-result') // can be used with true or false
// Regular expression assert
->assert('regexp', '/some-regular-expression/i')
// Array assertions
->assert('isarray') // Assert that result is an array
->assert('isarray', '[]==5') // Assert that array has a count of 5, can be used with true or false
->assert('isarray', '[3]==example') // Assert that array index 3 is equal to example, can be used with true or false
->assert('arrayhaskey', 'some-key-index')
->setIndexToTest('someIndex') // Explicitly set the index to test
// Object assertions
->assert('isobject') // Assert that resultant is an object
->assert('isobject', $classType) // Assert that the resultant object is of type $classType
->setPropertyToTest('property') // Sets the property to be tested
->assert('true', '->property==something') // Shortcut for the setPropertyToTest method, can be used with true or false
->callMethodToTest('isLoggedIn') // Call method 'isLoggedIn' on resultant object and set its value as the test subject
->assert('true') // Assert that the result of isLoggedIn is true
// Generic calls
->getTestResult(); // Returns the test result at any point
// 重复调用 - 仅可用于特定断言调用
->assert('isarray', '[3]==example') // Assert that array index 3 is equal to example
->repeat() // Will repeat isarray with no params
->repeat('[1]==repeated') // will repeat assert isarray with index 1 equal to repeated
->repeat('[]==10') // will repeat assert is array with param array count equal to 10
// 重置初始结果回测试
->resetResultToTest();
* Examples
Setting your test class
// YourProject/Src/Bundle/Test/YourTestClass.Test.php
$this->SymfMockProvider = $this->getMockProvider('Symfony2');
$this->setTestObject('Bundles\CampaignsBundle\Service\CampaignsService', array(
'entityManager' => $this->SymfMockProvider->getEntityManagerMock(),
'router' => $this->SymfMockProvider->getRouterMock(),
'translator' => $this->SymfMockProvider->getTranslatorMock()
));
Altering your test class's dependency
$entityManager = $this->SymfMockProvider->getEntityManagerMock();
$this->resetTestObjectArgument('entityManager', $entityManager);
A cleaner and more contained way to mock (chain-mock)
PHPUnit standard
// YourProject/Src/Bundle/Test/YourTestClass.Test.php
// User mock to be injected in assertRepoMock $userMock = $this->getUserMock(); $userMock->expects($this->any());
->method('getEmail')
->will($this->returnValue('example@phpunitAssister.com'));
// assertRepoMock to be injected in entityManager $assertRepoMock = $this->SymfMockProvider->getRepositoryMock('AssetBundle:Image'); $assertRepoMock->expects($this->exactly(1));
->method('find')
->with(12)
->will($this->returnValue($userMock));
// 包含模拟对象的对象 $entityManager = $this->SymfMockProvider->getEntityManagerMock(); $entityManager->expects($this->exactly(2));
->method('getRepository')
->with('AssetBundle:Image')
->will($this->returnValue($assertRepoMock));
PHPUnit assister - chain mocking the entity manager in symfony2
// YourProject/Src/Bundle/Test/YourTestClass.Test.php
// 从entityManager开始 $entityManager = $this->setmo($this->SymfMockProvider->getEntityManagerMock());
->mm('getRepository', [
'expects' => $this->exactly(2),
'with' => 'AssetBundle:Image',
// Inject the mock directly, doesnt need to stored in another variable
'will' => $this->returnValue($this->SymfMockProvider->getRepositoryMock('AssetBundle:Image'))
])
// Use the then call to further mock methods of the previously set object in the will clause
->then('find', [
'expects' => $this->exactly(1),
'with' => 12,
'will' => $this->returnValue($this->getUserMock())
])
// This will mock a method on the $this->getUserMock() resultant object
->then('getEmail', [
//Omit expects as its default value is $this->any()
'will' => $this->returnValue('example@phpunitAssister.com')
])
// Finally get the mocked object to inject into the test object
->getmo();
To use the userMock and AssetRepoMock from the previous example you can do
list($entityManager, $assetRepoMock, $userMock) = $this->setmo($this->SymfMockProvider->getEntityManagerMock());
->mm('getRepository', [
'expects' => $this->exactly(2),
'with' => 'AssetBundle:Image',
// Inject the mock directly, doesnt need to stored in another variable
'will' => $this->returnValue($this->SymfMockProvider->getRepositoryMock('AssetBundle:Image'))
])
// Use the then call to further mock methods of the previously set object in the will clause
->then('find', [
'expects' => $this->exactly(1),
'with' => 12,
'will' => $this->returnValue($this->getUserMock())
])
// This will mock a method on the $this->getUserMock() resultant object
->then('getEmail', [
//Omit expects as its default value is $this->any()
'will' => $this->returnValue('example@phpunitAssister.com')
])
// Getmos call gives you call mocks in sequential order
->getmos();
Calling test methods and chained Assertions
// YourProject/Src/Bundle/Test/YourTestClass.Test.php
... // 模拟
// 设置要测试的方法 $this->tm('exampleMethod');
// Specify params of method if any
->with($param1, $param2)
// assert if its an object, can also provide a specific object to test against
->assert('isobject', $optionalSpecificObject)
// call a method on the resultant object to further test its values
->callMethodToTest('isLoggedIn')
// check if the result of the isLoggedIn call is true
->assert('true');
Calling a private/protected method to test
$this->setTestObjectMethodAccessible() // 或 $this->setma();
->tm('privateMethod')->with()
->assert...
The `->setTestObjectMethodAccessible` will set the next tested method using the `->tm` call to public accessibility. Must be called before the `->with` call in order to work.
To get the mock provider you can use `$this->provider` which essentially is the same as `$this->getMockProvider()`. Note that this will provide you with basic mocking capabilities. To create a new mock object you can use
// 参数在此情况下是可选的,这将提供一个构造函数已禁用的新模拟。 $this->provider->getNewMock('\Your\Class', $args);
Creating extensions
-------------------
To create an extension place your extension mock provider in the extensions folder (Src/Extensions) with the namespace PHPUnitAssister\Extensions, the filenaming convention is `nameOfYourExtension.Class.php`
Once you have placed it in extensions folder, you can access your extension methods using the getMockProvider call
// YourProject/Src/Bundle/Test/YourTestClass.Test.php ... // 任何代码
$this->getMockProvider('name-of-your-extension-without-mockProvider-extension');