comparison core/tests/Drupal/Tests/UnitTestCase.php @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:c75dbcec494b
1 <?php
2
3 namespace Drupal\Tests;
4
5 use Drupal\Component\FileCache\FileCacheFactory;
6 use Drupal\Component\Utility\NestedArray;
7 use Drupal\Component\Utility\Random;
8 use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
9 use Drupal\Core\DependencyInjection\ContainerBuilder;
10 use Drupal\Core\StringTranslation\TranslatableMarkup;
11 use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
12 use PHPUnit\Framework\TestCase;
13
14 /**
15 * Provides a base class and helpers for Drupal unit tests.
16 *
17 * @ingroup testing
18 */
19 abstract class UnitTestCase extends TestCase {
20
21 use PhpunitCompatibilityTrait;
22
23 /**
24 * The random generator.
25 *
26 * @var \Drupal\Component\Utility\Random
27 */
28 protected $randomGenerator;
29
30 /**
31 * The app root.
32 *
33 * @var string
34 */
35 protected $root;
36
37 /**
38 * {@inheritdoc}
39 */
40 protected function setUp() {
41 parent::setUp();
42 // Ensure that an instantiated container in the global state of \Drupal from
43 // a previous test does not leak into this test.
44 \Drupal::unsetContainer();
45
46 // Ensure that the NullFileCache implementation is used for the FileCache as
47 // unit tests should not be relying on caches implicitly.
48 FileCacheFactory::setConfiguration([FileCacheFactory::DISABLE_CACHE => TRUE]);
49 // Ensure that FileCacheFactory has a prefix.
50 FileCacheFactory::setPrefix('prefix');
51
52 $this->root = dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
53 }
54
55 /**
56 * Generates a unique random string containing letters and numbers.
57 *
58 * @param int $length
59 * Length of random string to generate.
60 *
61 * @return string
62 * Randomly generated unique string.
63 *
64 * @see \Drupal\Component\Utility\Random::name()
65 */
66 public function randomMachineName($length = 8) {
67 return $this->getRandomGenerator()->name($length, TRUE);
68 }
69
70 /**
71 * Gets the random generator for the utility methods.
72 *
73 * @return \Drupal\Component\Utility\Random
74 * The random generator
75 */
76 protected function getRandomGenerator() {
77 if (!is_object($this->randomGenerator)) {
78 $this->randomGenerator = new Random();
79 }
80 return $this->randomGenerator;
81 }
82
83 /**
84 * Asserts if two arrays are equal by sorting them first.
85 *
86 * @param array $expected
87 * @param array $actual
88 * @param string $message
89 */
90 protected function assertArrayEquals(array $expected, array $actual, $message = NULL) {
91 ksort($expected);
92 ksort($actual);
93 $this->assertEquals($expected, $actual, $message);
94 }
95
96 /**
97 * Returns a stub config factory that behaves according to the passed array.
98 *
99 * Use this to generate a config factory that will return the desired values
100 * for the given config names.
101 *
102 * @param array $configs
103 * An associative array of configuration settings whose keys are
104 * configuration object names and whose values are key => value arrays for
105 * the configuration object in question. Defaults to an empty array.
106 *
107 * @return \PHPUnit_Framework_MockObject_MockBuilder
108 * A MockBuilder object for the ConfigFactory with the desired return
109 * values.
110 */
111 public function getConfigFactoryStub(array $configs = []) {
112 $config_get_map = [];
113 $config_editable_map = [];
114 // Construct the desired configuration object stubs, each with its own
115 // desired return map.
116 foreach ($configs as $config_name => $config_values) {
117 // Define a closure over the $config_values, which will be used as a
118 // returnCallback below. This function will mimic
119 // \Drupal\Core\Config\Config::get and allow using dotted keys.
120 $config_get = function ($key = '') use ($config_values) {
121 // Allow to pass in no argument.
122 if (empty($key)) {
123 return $config_values;
124 }
125 // See if we have the key as is.
126 if (isset($config_values[$key])) {
127 return $config_values[$key];
128 }
129 $parts = explode('.', $key);
130 $value = NestedArray::getValue($config_values, $parts, $key_exists);
131 return $key_exists ? $value : NULL;
132 };
133
134 $immutable_config_object = $this->getMockBuilder('Drupal\Core\Config\ImmutableConfig')
135 ->disableOriginalConstructor()
136 ->getMock();
137 $immutable_config_object->expects($this->any())
138 ->method('get')
139 ->will($this->returnCallback($config_get));
140 $config_get_map[] = [$config_name, $immutable_config_object];
141
142 $mutable_config_object = $this->getMockBuilder('Drupal\Core\Config\Config')
143 ->disableOriginalConstructor()
144 ->getMock();
145 $mutable_config_object->expects($this->any())
146 ->method('get')
147 ->will($this->returnCallback($config_get));
148 $config_editable_map[] = [$config_name, $mutable_config_object];
149 }
150 // Construct a config factory with the array of configuration object stubs
151 // as its return map.
152 $config_factory = $this->createMock('Drupal\Core\Config\ConfigFactoryInterface');
153 $config_factory->expects($this->any())
154 ->method('get')
155 ->will($this->returnValueMap($config_get_map));
156 $config_factory->expects($this->any())
157 ->method('getEditable')
158 ->will($this->returnValueMap($config_editable_map));
159 return $config_factory;
160 }
161
162 /**
163 * Returns a stub config storage that returns the supplied configuration.
164 *
165 * @param array $configs
166 * An associative array of configuration settings whose keys are
167 * configuration object names and whose values are key => value arrays
168 * for the configuration object in question.
169 *
170 * @return \Drupal\Core\Config\StorageInterface
171 * A mocked config storage.
172 */
173 public function getConfigStorageStub(array $configs) {
174 $config_storage = $this->createMock('Drupal\Core\Config\NullStorage');
175 $config_storage->expects($this->any())
176 ->method('listAll')
177 ->will($this->returnValue(array_keys($configs)));
178
179 foreach ($configs as $name => $config) {
180 $config_storage->expects($this->any())
181 ->method('read')
182 ->with($this->equalTo($name))
183 ->will($this->returnValue($config));
184 }
185 return $config_storage;
186 }
187
188 /**
189 * Mocks a block with a block plugin.
190 *
191 * @param string $machine_name
192 * The machine name of the block plugin.
193 *
194 * @return \Drupal\block\BlockInterface|\PHPUnit_Framework_MockObject_MockObject
195 * The mocked block.
196 *
197 * @deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Unit test
198 * base classes should not have dependencies on extensions. Set up mocks in
199 * individual tests.
200 *
201 * @see https://www.drupal.org/node/2896072
202 */
203 protected function getBlockMockWithMachineName($machine_name) {
204 $plugin = $this->getMockBuilder('Drupal\Core\Block\BlockBase')
205 ->disableOriginalConstructor()
206 ->getMock();
207 $plugin->expects($this->any())
208 ->method('getMachineNameSuggestion')
209 ->will($this->returnValue($machine_name));
210
211 $block = $this->getMockBuilder('Drupal\block\Entity\Block')
212 ->disableOriginalConstructor()
213 ->getMock();
214 $block->expects($this->any())
215 ->method('getPlugin')
216 ->will($this->returnValue($plugin));
217 @trigger_error(__METHOD__ . ' is deprecated in Drupal 8.5.x, will be removed before Drupal 9.0.0. Unit test base classes should not have dependencies on extensions. Set up mocks in individual tests.', E_USER_DEPRECATED);
218 return $block;
219 }
220
221 /**
222 * Returns a stub translation manager that just returns the passed string.
223 *
224 * @return \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\StringTranslation\TranslationInterface
225 * A mock translation object.
226 */
227 public function getStringTranslationStub() {
228 $translation = $this->createMock('Drupal\Core\StringTranslation\TranslationInterface');
229 $translation->expects($this->any())
230 ->method('translate')
231 ->willReturnCallback(function ($string, array $args = [], array $options = []) use ($translation) {
232 return new TranslatableMarkup($string, $args, $options, $translation);
233 });
234 $translation->expects($this->any())
235 ->method('translateString')
236 ->willReturnCallback(function (TranslatableMarkup $wrapper) {
237 return $wrapper->getUntranslatedString();
238 });
239 $translation->expects($this->any())
240 ->method('formatPlural')
241 ->willReturnCallback(function ($count, $singular, $plural, array $args = [], array $options = []) use ($translation) {
242 $wrapper = new PluralTranslatableMarkup($count, $singular, $plural, $args, $options, $translation);
243 return $wrapper;
244 });
245 return $translation;
246 }
247
248 /**
249 * Sets up a container with a cache tags invalidator.
250 *
251 * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_validator
252 * The cache tags invalidator.
253 *
254 * @return \Symfony\Component\DependencyInjection\ContainerInterface|\PHPUnit_Framework_MockObject_MockObject
255 * The container with the cache tags invalidator service.
256 */
257 protected function getContainerWithCacheTagsInvalidator(CacheTagsInvalidatorInterface $cache_tags_validator) {
258 $container = $this->createMock('Symfony\Component\DependencyInjection\ContainerInterface');
259 $container->expects($this->any())
260 ->method('get')
261 ->with('cache_tags.invalidator')
262 ->will($this->returnValue($cache_tags_validator));
263
264 \Drupal::setContainer($container);
265 return $container;
266 }
267
268 /**
269 * Returns a stub class resolver.
270 *
271 * @return \Drupal\Core\DependencyInjection\ClassResolverInterface|\PHPUnit_Framework_MockObject_MockObject
272 * The class resolver stub.
273 */
274 protected function getClassResolverStub() {
275 $class_resolver = $this->createMock('Drupal\Core\DependencyInjection\ClassResolverInterface');
276 $class_resolver->expects($this->any())
277 ->method('getInstanceFromDefinition')
278 ->will($this->returnCallback(function ($class) {
279 if (is_subclass_of($class, 'Drupal\Core\DependencyInjection\ContainerInjectionInterface')) {
280 return $class::create(new ContainerBuilder());
281 }
282 else {
283 return new $class();
284 }
285 }));
286 return $class_resolver;
287 }
288
289 }