class ProtectedPrivatesTest in Examples for Developers 8
Same name and namespace in other branches
- 3.x modules/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 PhpunitCompatibilityTrait
- class \Drupal\Tests\phpunit_example\Unit\ProtectedPrivatesTest
Expanded class hierarchy of ProtectedPrivatesTest
Related topics
File
- 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 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 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
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
PhpunitCompatibilityTrait:: |
public | function | Returns a mock object for the specified class using the available method. | |
PhpunitCompatibilityTrait:: |
public | function | Compatibility layer for PHPUnit 6 to support PHPUnit 4 code. | |
ProtectedPrivatesTest:: |
public | function | Bad data provider. | |
ProtectedPrivatesTest:: |
public | function | Good data provider. | |
ProtectedPrivatesTest:: |
public | function | Get an accessible method using reflection. | |
ProtectedPrivatesTest:: |
public | function | Test ProtectedPrivate::privateAdd(). | |
ProtectedPrivatesTest:: |
public | function | Test ProtectedPrivate::privateAdd() with bad data. | |
ProtectedPrivatesTest:: |
public | function | Test ProtectedPrivates::protectedAdd() using a stub class. | |
ProtectedPrivatesTest:: |
public | function | Test ProtectedPrivates::protectedAdd() with bad data using a stub class. | |
UnitTestCase:: |
protected | property | The random generator. | |
UnitTestCase:: |
protected | property | The app root. | 1 |
UnitTestCase:: |
protected | function | Asserts if two arrays are equal by sorting them first. | |
UnitTestCase:: |
protected | function | Mocks a block with a block plugin. | 1 |
UnitTestCase:: |
protected | function | Returns a stub class resolver. | |
UnitTestCase:: |
public | function | Returns a stub config factory that behaves according to the passed array. | |
UnitTestCase:: |
public | function | Returns a stub config storage that returns the supplied configuration. | |
UnitTestCase:: |
protected | function | Sets up a container with a cache tags invalidator. | |
UnitTestCase:: |
protected | function | Gets the random generator for the utility methods. | |
UnitTestCase:: |
public | function | Returns a stub translation manager that just returns the passed string. | |
UnitTestCase:: |
public | function | Generates a unique random string containing letters and numbers. | |
UnitTestCase:: |
protected | function | 340 |