class ProtectedPrivatesTest
Same name in other branches
- 3.x modules/phpunit_example/tests/src/Unit/ProtectedPrivatesTest.php \Drupal\Tests\phpunit_example\Unit\ProtectedPrivatesTest
- 8.x-1.x phpunit_example/tests/src/Unit/ProtectedPrivatesTest.php \Drupal\Tests\phpunit_example\Unit\ProtectedPrivatesTest
ProtectedPrivates unit testing of restricted methods.
This test case demonstrates the following unit testing patterns and topics:
- Using reflection to test private class methods.
- Using subclassing to test protected class methods.
If you are reading this and don't understand the basics of unit testing, start reading AddClassTest instead.
This test class uses reflection and subclassing to work around method access problems. Since, by design, a private method is inaccessible, we have to use reflection to gain access to the method for our own purposes.
The getAccessibleMethod() method demonstrates a way to do this.
Once we've set the method to be accessible, we can use it as if it were public.
The same technique can be used for protected methods. However, there might be times when it makes more sense to subclass the class under test, and just make a public accessor method that way. So we demonstrate that here in testProtectedAdd().
@group phpunit_example @group examples
Hierarchy
- class \Drupal\Tests\UnitTestCase extends \PHPUnit\Framework\TestCase uses \Drupal\Tests\Traits\PhpUnitWarnings, \Drupal\Tests\PhpUnitCompatibilityTrait, \Prophecy\PhpUnit\ProphecyTrait, \Symfony\Bridge\PhpUnit\ExpectDeprecationTrait, \Drupal\Tests\RandomGeneratorTrait
- class \Drupal\Tests\phpunit_example\Unit\ProtectedPrivatesTest extends \Drupal\Tests\UnitTestCase
Expanded class hierarchy of ProtectedPrivatesTest
Related topics
File
-
modules/
phpunit_example/ tests/ src/ Unit/ ProtectedPrivatesTest.php, line 41
Namespace
Drupal\Tests\phpunit_example\UnitView source
class ProtectedPrivatesTest extends UnitTestCase {
/**
* Get an accessible method using reflection.
*/
public function getAccessibleMethod($class_name, $method_name) {
$class = new \ReflectionClass($class_name);
$method = $class->getMethod($method_name);
$method->setAccessible(TRUE);
return $method;
}
/**
* Good data provider.
*/
public static function addDataProvider() {
return [
[
5,
2,
3,
],
];
}
/**
* Test ProtectedPrivate::privateAdd().
*
* We want to test a private method on a class. This is problematic
* because, by design, we don't have access to this method. However,
* we do have a tool available to help us out with this problem:
* We can override the accessibility of a method using reflection.
*
* @dataProvider addDataProvider
*/
public function testPrivateAdd($expected, $a, $b) {
// Get a reflected, accessible version of the privateAdd() method.
$private_method = $this->getAccessibleMethod('Drupal\\phpunit_example\\ProtectedPrivates', 'privateAdd');
// Create a new ProtectedPrivates object.
$pp = new ProtectedPrivates();
// Use the reflection to invoke on the object.
$sum = $private_method->invokeArgs($pp, [
$a,
$b,
]);
// Make an assertion.
$this->assertEquals($expected, $sum);
}
/**
* Bad data provider.
*/
public static function addBadDataProvider() {
return [
[
'string',
[],
],
];
}
/**
* Test ProtectedPrivate::privateAdd() with bad data.
*
* This is essentially the same test as testPrivateAdd(), but using
* non-numeric data. This lets us test the exception-throwing ability
* of this private method.
*
* @dataProvider addBadDataProvider
*/
public function testPrivateAddBadData($a, $b) {
// Get a reflected, accessible version of the privateAdd() method.
$private_method = $this->getAccessibleMethod('Drupal\\phpunit_example\\ProtectedPrivates', 'privateAdd');
// Create a new ProtectedPrivates object.
$pp = new ProtectedPrivates();
// Use the reflection to invoke on the object.
// This should throw an exception.
$this->expectException(\InvalidArgumentException::class);
$private_method->invokeArgs($pp, [
$a,
$b,
]);
}
/**
* Test ProtectedPrivates::protectedAdd() using a stub class.
*
* We could use the same reflection technique to test protected
* methods, just like we did with private ones.
*
* But sometimes it might make more sense to use a stub class
* which will have access to the protected method. That's what
* we'll demonstrate here.
*
* @dataProvider addDataProvider
*/
public function testProtectedAdd($expected, $a, $b) {
$stub = new ProtectedPrivatesSubclass();
$this->assertEquals($expected, $stub->subclassProtectedAdd($a, $b));
}
/**
* Test ProtectedPrivates::protectedAdd() with bad data using a stub class.
*
* This test is similar to testProtectedAdd(), but expects an exception.
*
* @dataProvider addBadDataProvider
*/
public function testProtectedAddBadData($a, $b) {
$stub = new ProtectedPrivatesSubclass();
$this->expectException(\InvalidArgumentException::class);
$stub->subclassProtectedAdd($a, $b);
}
}
Members
Title Sort descending | Deprecated | Modifiers | Object type | Summary | Overrides |
---|---|---|---|---|---|
PhpUnitWarnings::$deprecationWarnings | private static | property | Deprecation warnings from PHPUnit to raise with @trigger_error(). | ||
PhpUnitWarnings::addWarning | public | function | Converts PHPUnit deprecation warnings to E_USER_DEPRECATED. | ||
ProtectedPrivatesTest::addBadDataProvider | public static | function | Bad data provider. | ||
ProtectedPrivatesTest::addDataProvider | public static | function | Good data provider. | ||
ProtectedPrivatesTest::getAccessibleMethod | public | function | Get an accessible method using reflection. | ||
ProtectedPrivatesTest::testPrivateAdd | public | function | Test ProtectedPrivate::privateAdd(). | ||
ProtectedPrivatesTest::testPrivateAddBadData | public | function | Test ProtectedPrivate::privateAdd() with bad data. | ||
ProtectedPrivatesTest::testProtectedAdd | public | function | Test ProtectedPrivates::protectedAdd() using a stub class. | ||
ProtectedPrivatesTest::testProtectedAddBadData | public | function | Test ProtectedPrivates::protectedAdd() with bad data using a stub class. | ||
RandomGeneratorTrait::getRandomGenerator | protected | function | Gets the random generator for the utility methods. | ||
RandomGeneratorTrait::randomMachineName | protected | function | Generates a unique random string containing letters and numbers. | ||
RandomGeneratorTrait::randomObject | public | function | Generates a random PHP object. | ||
RandomGeneratorTrait::randomString | public | function | Generates a pseudo-random string of ASCII characters of codes 32 to 126. | ||
RandomGeneratorTrait::randomStringValidate | Deprecated | public | function | Callback for random string validation. | |
UnitTestCase::$root | protected | property | The app root. | 1 | |
UnitTestCase::getClassResolverStub | protected | function | Returns a stub class resolver. | ||
UnitTestCase::getConfigFactoryStub | public | function | Returns a stub config factory that behaves according to the passed array. | ||
UnitTestCase::getConfigStorageStub | public | function | Returns a stub config storage that returns the supplied configuration. | ||
UnitTestCase::getContainerWithCacheTagsInvalidator | protected | function | Sets up a container with a cache tags invalidator. | ||
UnitTestCase::getStringTranslationStub | public | function | Returns a stub translation manager that just returns the passed string. | ||
UnitTestCase::setUp | protected | function | 358 | ||
UnitTestCase::setUpBeforeClass | public static | function | |||
UnitTestCase::__get | public | function |