Unverified Commit f320141d authored by larowlan's avatar larowlan
Browse files

Issue #2795317 by hswong3i, alexpott, Lendude, bircher, dawehner, martin107,...

Issue #2795317 by hswong3i, alexpott, Lendude, bircher, dawehner, martin107, Jo Fitzgerald, mondrake: Allow PHPUnit 6+ support for object mocking
parent b5b3949b
......@@ -28,7 +28,7 @@ class UpdateFetcherTest extends UnitTestCase {
*/
protected function setUp() {
$config_factory = $this->getConfigFactoryStub(['update.settings' => ['fetch_url' => 'http://www.example.com']]);
$http_client_mock = $this->getMock('\GuzzleHttp\ClientInterface');
$http_client_mock = $this->createMock('\GuzzleHttp\ClientInterface');
$this->updateFetcher = new UpdateFetcher($config_factory, $http_client_mock);
}
......
......@@ -20,6 +20,7 @@
use Drupal\simpletest\AssertContentTrait;
use Drupal\Tests\AssertHelperTrait;
use Drupal\Tests\ConfigTestTrait;
use Drupal\Tests\PhpunitCompatibilityTrait;
use Drupal\Tests\RandomGeneratorTrait;
use Drupal\Tests\TestRequirementsTrait;
use Drupal\simpletest\TestServiceProvider;
......@@ -76,6 +77,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa
use RandomGeneratorTrait;
use ConfigTestTrait;
use TestRequirementsTrait;
use PhpunitCompatibilityTrait;
/**
* {@inheritdoc}
......
......@@ -66,6 +66,7 @@ abstract class BrowserTestBase extends TestCase {
createUser as drupalCreateUser;
}
use XdebugRequestTrait;
use PhpunitCompatibilityTrait;
/**
* The database prefix of this test run.
......
<?php
namespace Drupal\Tests;
/**
* Makes Drupal's test API forward compatible with multiple versions of PHPUnit.
*/
trait PhpunitCompatibilityTrait {
/**
* Returns a mock object for the specified class using the available method.
*
* The getMock method does not exist in PHPUnit 6. To provide backward
* compatibility this trait provides the getMock method and uses createMock if
* this method is available on the parent class.
*
* @param string $originalClassName
* Name of the class to mock.
* @param array|null $methods
* When provided, only methods whose names are in the array are replaced
* with a configurable test double. The behavior of the other methods is not
* changed. Providing null means that no methods will be replaced.
* @param array $arguments
* Parameters to pass to the original class' constructor.
* @param string $mockClassName
* Class name for the generated test double class.
* @param bool $callOriginalConstructor
* Can be used to disable the call to the original class' constructor.
* @param bool $callOriginalClone
* Can be used to disable the call to the original class' clone constructor.
* @param bool $callAutoload
* Can be used to disable __autoload() during the generation of the test
* double class.
* @param bool $cloneArguments
* Enables the cloning of arguments passed to mocked methods.
* @param bool $callOriginalMethods
* Enables the invocation of the original methods.
* @param object $proxyTarget
* Sets the proxy target.
*
* @see \PHPUnit_Framework_TestCase::getMock
* @see https://github.com/sebastianbergmann/phpunit/wiki/Release-Announcement-for-PHPUnit-5.4.0
*
* @return \PHPUnit_Framework_MockObject_MockObject
*
* @deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0.
* Use \Drupal\Tests\PhpunitCompatibilityTrait::createMock() instead.
*
* @see https://www.drupal.org/node/2907725
*/
public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE, $callOriginalMethods = FALSE, $proxyTarget = NULL) {
if (!$this->supports('getMock')) {
$mock = $this->getMockBuilder($originalClassName)
->setMethods($methods)
->setConstructorArgs($arguments)
->setMockClassName($mockClassName)
->setProxyTarget($proxyTarget);
if ($callOriginalConstructor) {
$mock->enableOriginalConstructor();
}
else {
$mock->disableOriginalConstructor();
}
if ($callOriginalClone) {
$mock->enableOriginalClone();
}
else {
$mock->disableOriginalClone();
}
if ($callAutoload) {
$mock->enableAutoload();
}
else {
$mock->disableAutoload();
}
if ($cloneArguments) {
$mock->enableArgumentCloning();
}
else {
$mock->disableArgumentCloning();
}
if ($callOriginalMethods) {
$mock->enableProxyingToOriginalMethods();
}
else {
$mock->disableProxyingToOriginalMethods();
}
return $mock->getMock();
}
else {
return parent::getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $proxyTarget);
}
}
/**
* Returns a mock object for the specified class using the available method.
*
* The createMock method does not exist in PHPUnit 4. To provide forward
* compatibility this trait provides the createMock method and uses createMock
* if this method is available on the parent class or falls back to getMock if
* it isn't.
*
* @param string $originalClassName
* Name of the class to mock.
*
* @see \PHPUnit_Framework_TestCase::getMock
*
* @return \PHPUnit_Framework_MockObject_MockObject
*/
public function createMock($originalClassName) {
if ($this->supports('createMock')) {
return parent::createMock($originalClassName);
}
else {
return $this->getMock($originalClassName, [], [], '', FALSE, FALSE);
}
}
/**
* Checks if the trait is used in a class that has a method.
*
* @param string $method
* Method to check.
*
* @return bool
* TRUE if the method is supported, FALSE if not.
*/
private function supports($method) {
// Get the parent class of the currently running test class.
$parent = get_parent_class($this);
// Ensure that the method_exists() check on the createMock method is carried
// out on the first parent of $this that does not have access to this
// trait's methods. This is because the trait also has a method called
// createMock(). Most often the check will be made on
// \PHPUnit\Framework\TestCase.
while (method_exists($parent, 'supports')) {
$parent = get_parent_class($parent);
}
return method_exists($parent, $method);
}
}
<?php
namespace Drupal\Tests;
/**
* Tests the PHPUnit forward compatibility trait.
*
* @coversDefaultClass \Drupal\Tests\PhpunitCompatibilityTrait
* @group Tests
*/
class PhpunitCompatibilityTraitTest extends UnitTestCase {
/**
* Tests that getMock is available and calls the correct parent method.
*
* @covers ::getMock
* @dataProvider providerMockVersions
*/
public function testGetMock($className, $expected) {
$class = new $className();
$this->assertSame($expected, $class->getMock($this->randomMachineName()));
}
/**
* Tests that createMock is available and calls the correct parent method.
*
* @covers ::createMock
* @dataProvider providerMockVersions
*/
public function testCreateMock($className, $expected) {
$class = new $className();
$this->assertSame($expected, $class->createMock($this->randomMachineName()));
}
/**
* Returns the class names and the string they return.
*
* @return array
*/
public function providerMockVersions() {
return [
[UnitTestCasePhpunit4TestClass::class, 'PHPUnit 4'],
[UnitTestCasePhpunit4TestClassExtends::class, 'PHPUnit 4'],
[UnitTestCasePhpunit6TestClass::class, 'PHPUnit 6'],
[UnitTestCasePhpunit6TestClassExtends::class, 'PHPUnit 6'],
];
}
}
/**
* Test class for \PHPUnit\Framework\TestCase in PHPUnit 4.
*/
class Phpunit4TestClass {
public function getMock($originalClassName) {
return 'PHPUnit 4';
}
}
/**
* Test class for \PHPUnit\Framework\TestCase in PHPUnit 6.
*/
class Phpunit6TestClass {
public function createMock($originalClassName) {
return 'PHPUnit 6';
}
public function getMockbuilder() {
return new Mockbuilder();
}
}
/**
* Test double for PHPUnit_Framework_MockObject_MockBuilder.
*/
class Mockbuilder {
public function __call($name, $arguments) {
return $this;
}
public function getMock() {
return 'PHPUnit 6';
}
}
/**
* Test class for \Drupal\Tests\UnitTestCase with PHPUnit 4.
*/
class UnitTestCasePhpunit4TestClass extends Phpunit4TestClass {
use PhpunitCompatibilityTrait;
}
/**
* Test class for \Drupal\Tests\UnitTestCase with PHPUnit 4.
*/
class UnitTestCasePhpunit4TestClassExtends extends UnitTestCasePhpunit4TestClass {
}
/**
* Test class for \Drupal\Tests\UnitTestCase with PHPUnit 6.
*/
class UnitTestCasePhpunit6TestClass extends Phpunit6TestClass {
use PhpunitCompatibilityTrait;
}
/**
* Test class for \Drupal\Tests\UnitTestCase with PHPUnit 6.
*/
class UnitTestCasePhpunit6TestClassExtends extends UnitTestCasePhpunit6TestClass {
}
......@@ -17,6 +17,8 @@
*/
abstract class UnitTestCase extends TestCase {
use PhpunitCompatibilityTrait;
/**
* The random generator.
*
......@@ -135,7 +137,7 @@ public function getConfigFactoryStub(array $configs = []) {
}
// Construct a config factory with the array of configuration object stubs
// as its return map.
$config_factory = $this->getMock('Drupal\Core\Config\ConfigFactoryInterface');
$config_factory = $this->createMock('Drupal\Core\Config\ConfigFactoryInterface');
$config_factory->expects($this->any())
->method('get')
->will($this->returnValueMap($config_get_map));
......@@ -157,7 +159,7 @@ public function getConfigFactoryStub(array $configs = []) {
* A mocked config storage.
*/
public function getConfigStorageStub(array $configs) {
$config_storage = $this->getMock('Drupal\Core\Config\NullStorage');
$config_storage = $this->createMock('Drupal\Core\Config\NullStorage');
$config_storage->expects($this->any())
->method('listAll')
->will($this->returnValue(array_keys($configs)));
......@@ -211,7 +213,7 @@ protected function getBlockMockWithMachineName($machine_name) {
* A mock translation object.
*/
public function getStringTranslationStub() {
$translation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
$translation = $this->createMock('Drupal\Core\StringTranslation\TranslationInterface');
$translation->expects($this->any())
->method('translate')
->willReturnCallback(function ($string, array $args = [], array $options = []) use ($translation) {
......@@ -241,7 +243,7 @@ public function getStringTranslationStub() {
* The container with the cache tags invalidator service.
*/
protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInterface $cache_tags_validator) {
$container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container = $this->createMock('Symfony\Component\DependencyInjection\ContainerInterface');
$container->expects($this->any())
->method('get')
->with('cache_tags.invalidator')
......@@ -258,7 +260,7 @@ protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInte
* The class resolver stub.
*/
protected function getClassResolverStub() {
$class_resolver = $this->getMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
$class_resolver = $this->createMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
$class_resolver->expects($this->any())
->method('getInstanceFromDefinition')
->will($this->returnCallback(function ($class) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment