Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New mock() test helper and expanded MockCache with assertions. #4831

Merged
merged 9 commits into from
Jun 21, 2021
103 changes: 58 additions & 45 deletions system/Cache/CacheFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use CodeIgniter\Cache\Exceptions\CacheException;
use CodeIgniter\Exceptions\CriticalError;
use CodeIgniter\Test\Mock\MockCache;
use Config\Cache;

/**
Expand All @@ -22,59 +23,71 @@
*/
class CacheFactory
{
/**
* Attempts to create the desired cache handler, based upon the
*
* @param Cache $config
* @param string|null $handler
* @param string|null $backup
*
* @return CacheInterface
*/
public static function getHandler(Cache $config, string $handler = null, string $backup = null)
{
if (! isset($config->validHandlers) || ! is_array($config->validHandlers)) {
throw CacheException::forInvalidHandlers();
}
/**
* The class to use when mocking
*
* @var string
*/
public static $mockClass = MockCache::class;

if (! isset($config->handler) || ! isset($config->backupHandler)) {
throw CacheException::forNoBackup();
}
/**
* The service to inject the mock as
*
* @var string
*/
public static $mockServiceName = 'cache';

$handler = ! empty($handler) ? $handler : $config->handler;
$backup = ! empty($backup) ? $backup : $config->backupHandler;
/**
* Attempts to create the desired cache handler, based upon the
*
* @param Cache $config
* @param string|null $handler
* @param string|null $backup
*
* @return CacheInterface
*/
public static function getHandler(Cache $config, string $handler = null, string $backup = null)
{
if (! isset($config->validHandlers) || ! is_array($config->validHandlers)) {
throw CacheException::forInvalidHandlers();
}

if (! array_key_exists($handler, $config->validHandlers) || ! array_key_exists($backup, $config->validHandlers)) {
throw CacheException::forHandlerNotFound();
}
if (! isset($config->handler) || ! isset($config->backupHandler)) {
throw CacheException::forNoBackup();
}

// Get an instance of our handler.
$adapter = new $config->validHandlers[$handler]($config);
$handler = ! empty($handler) ? $handler : $config->handler;
$backup = ! empty($backup) ? $backup : $config->backupHandler;

if (! $adapter->isSupported()) {
$adapter = new $config->validHandlers[$backup]($config);
if (! array_key_exists($handler, $config->validHandlers) || ! array_key_exists($backup, $config->validHandlers)) {
throw CacheException::forHandlerNotFound();
}

if (! $adapter->isSupported()) {
// Log stuff here, don't throw exception. No need to raise a fuss.
// Fall back to the dummy adapter.
$adapter = new $config->validHandlers['dummy']();
}
}
// Get an instance of our handler.
$adapter = new $config->validHandlers[$handler]($config);

// If $adapter->initialization throws a CriticalError exception, we will attempt to
// use the $backup handler, if that also fails, we resort to the dummy handler.
try {
$adapter->initialize();
} catch (CriticalError $e) {
// log the fact that an exception occurred as well what handler we are resorting to
log_message('critical', $e->getMessage() . ' Resorting to using ' . $backup . ' handler.');
if (! $adapter->isSupported()) {
$adapter = new $config->validHandlers[$backup]($config);

// get the next best cache handler (or dummy if the $backup also fails)
$adapter = self::getHandler($config, $backup, 'dummy');
}
if (! $adapter->isSupported()) {
// Log stuff here, don't throw exception. No need to raise a fuss.
// Fall back to the dummy adapter.
$adapter = new $config->validHandlers['dummy']();
}
}

return $adapter;
}
// If $adapter->initialization throws a CriticalError exception, we will attempt to
// use the $backup handler, if that also fails, we resort to the dummy handler.
try {
$adapter->initialize();
} catch (CriticalError $e) {
// log the fact that an exception occurred as well what handler we are resorting to
log_message('critical', $e->getMessage() . ' Resorting to using ' . $backup . ' handler.');

//--------------------------------------------------------------------
// get the next best cache handler (or dummy if the $backup also fails)
$adapter = self::getHandler($config, $backup, 'dummy');
}

return $adapter;
}
}
25 changes: 25 additions & 0 deletions system/Exceptions/TestException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/**
* This file is part of the CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CodeIgniter\Exceptions;

/**
* Exception for automatic logging.
*/
class TestException extends CriticalError
{
use DebugTraceableTrait;

public static function forInvalidMockClass(string $name)
{
return new static(lang('Test.invalidMockClass', [$name]));
}
}
30 changes: 30 additions & 0 deletions system/Helpers/test_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
* file that was distributed with this source code.
*/

use CodeIgniter\Exceptions\TestException;
use CodeIgniter\Model;
use CodeIgniter\Test\Fabricator;
use Config\Services;

/**
* CodeIgniter Test Helpers
Expand Down Expand Up @@ -43,3 +45,31 @@ function fake($model, array $overrides = null, $persist = true)
return $fabricator->make();
}
}

if (! function_exists('mock'))
{
/**
* Used within our test suite to mock certain system tools.
*
* @param string $className Fully qualified class name
*/
function mock(string $className)
{
$mockClass = $className::$mockClass;
$mockService = $className::$mockServiceName ?? '';

if (empty($mockClass) || ! class_exists($mockClass))
{
throw TestException::forInvalidMockClass($mockClass);
}

$mock = new $mockClass();

if (! empty($mockService))
{
Services::injectMock($mockService, $mock);
}

return $mock;
}
}
15 changes: 15 additions & 0 deletions system/Language/en/Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

/**
* This file is part of the CodeIgniter 4 framework.
*
* (c) CodeIgniter Foundation <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

// Testing language settings
return [
'invalidMockClass' => '{0} is not a valid Mock class',
];
Loading