Refactor Factory class

With this code the Factory class will be used also to create Exceptions.

In order to do that, the AbstractRule::reportError() was changed, so the
tests of the AbstractRule class.

What this commit also does:
- Port code to PHP 7;
- Do not keep the default instance of the Factory in the Validator
  class;
- Make Factory final.
This commit is contained in:
Henrique Moody 2018-01-06 14:49:38 +01:00
parent 2417080c4e
commit 1f217dda66
No known key found for this signature in database
GPG key ID: 221E9281655813A6
13 changed files with 579 additions and 231 deletions

View file

@ -234,6 +234,7 @@ a rule and an exception to go with the rule.
To create a rule, you need to create a class that extends the AbstractRule class
and is within the Rules `namespace`. When the rule is called the logic inside the
validate method will be executed. Here's how the class should look:
```php
namespace My\Validation\Rules;
@ -253,6 +254,7 @@ with the name of the rule followed by the word Exception. The process of creatin
an Exception is similar to creating a rule but there are no methods in the
Exception class. Instead, you create one static property that includes an
array with the information below:
```php
namespace My\Validation\Exceptions;
@ -274,6 +276,7 @@ class MyRuleException extends ValidationException
So in the end, the folder structure for your Rules and Exceptions should look
something like the structure below. Note that the folders (and namespaces) are
plural but the actual Rules and Exceptions are singular.
```
My
+-- Validation
@ -283,20 +286,19 @@ My
+-- MyRule.php
```
If you want Validation to execute your rule (or rules) in the chain, you must
use `v::with()` passing your rule's namespace as an argument:
All classes in Validation are created by the `Factory` class. If you want
Validation to execute your rule (or rules) in the chain, you must overwrite the
default `Factory`.
```php
v::with('My\\Validation\\Rules\\');
Factory::setDefaultInstance(
new Factory(
['My\\Validation\\Rules'],
['My\\Validation\\Exceptions']
)
);
v::myRule(); // Try to load "My\Validation\Rules\MyRule" if any
```
By default `with()` appends the given prefix, but you can change this behavior
in order to overwrite default rules:
```php
v::with('My\\Validation\\Rules', true);
v::alnum(); // Try to use "My\Validation\Rules\Alnum" if any
v::alnum(); // Try to use "My\Validation\Rules\Alnum" if any, or else "Respect\Validation\Rules\Alnum"
```
## Validator name

View file

@ -0,0 +1,25 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Exceptions;
/**
* Exception for invalid classes.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*
* @since 2.0.0
*/
final class InvalidClassException extends ComponentException
{
}

View file

@ -0,0 +1,18 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Exceptions;
final class ValidatorException extends AllOfException
{
}

View file

@ -13,56 +13,234 @@ declare(strict_types=1);
namespace Respect\Validation;
use function array_map;
use function array_merge;
use function array_unique;
use function class_exists;
use function lcfirst;
use function Respect\Stringifier\stringify;
use ReflectionClass;
use ReflectionObject;
use Respect\Validation\Exceptions\ComponentException;
use Respect\Validation\Exceptions\InvalidClassException;
use Respect\Validation\Exceptions\ValidationException;
class Factory
/**
* Factory of objects.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*
* @since 0.8.0
*/
final class Factory
{
protected $rulePrefixes = ['Respect\\Validation\\Rules\\'];
private const DEFAULT_RULES_NAMESPACES = [
'Respect\\Validation\\Rules',
'Respect\\Validation\\Rules\\Locale',
'Respect\\Validation\\Rules\\SubdivisionCode',
];
public function getRulePrefixes()
private const DEFAULT_EXCEPTIONS_NAMESPACES = [
'Respect\\Validation\\Exceptions',
'Respect\\Validation\\Exceptions\\Locale',
'Respect\\Validation\\Exceptions\\SubdivisionCode',
];
/**
* Default instance of the Factory.
*
* @var Factory
*/
private static $defaultInstance;
/**
* @var string[]
*/
private $rulesNamespaces = [];
/**
* @var string[]
*/
private $exceptionsNamespaces = [];
/**
* Initializes the factory with the defined namespaces.
*
* If the default namespace is not in the array, it will be add to the end
* of the array.
*
* @param string[] $rulesNamespaces
* @param string[] $exceptionsNamespaces
*/
public function __construct(array $rulesNamespaces, array $exceptionsNamespaces)
{
return $this->rulePrefixes;
$this->rulesNamespaces = $this->filterNamespaces($rulesNamespaces, self::DEFAULT_RULES_NAMESPACES);
$this->exceptionsNamespaces = $this->filterNamespaces($exceptionsNamespaces, self::DEFAULT_EXCEPTIONS_NAMESPACES);
}
private function filterRulePrefix($rulePrefix)
/**
* Define the default instance of the Factory.
*
* @param Factory $defaultInstance
*/
public static function setDefaultInstance(self $defaultInstance): void
{
$namespaceSeparator = '\\';
$rulePrefix = rtrim($rulePrefix, $namespaceSeparator);
return $rulePrefix.$namespaceSeparator;
self::$defaultInstance = $defaultInstance;
}
public function appendRulePrefix($rulePrefix): void
/**
* Returns the default instance of the Factory.
*
* @return Factory
*/
public static function getDefaultInstance(): self
{
array_push($this->rulePrefixes, $this->filterRulePrefix($rulePrefix));
}
public function prependRulePrefix($rulePrefix): void
{
array_unshift($this->rulePrefixes, $this->filterRulePrefix($rulePrefix));
}
public function rule($ruleName, array $arguments = [])
{
if ($ruleName instanceof Validatable) {
return $ruleName;
if (null === self::$defaultInstance) {
self::$defaultInstance = new self(self::DEFAULT_RULES_NAMESPACES, self::DEFAULT_EXCEPTIONS_NAMESPACES);
}
foreach ($this->getRulePrefixes() as $prefix) {
$className = $prefix.ucfirst($ruleName);
return self::$defaultInstance;
}
/**
* Creates a rule.
*
* @param string $ruleName
* @param array $arguments
*
* @throws ComponentException
*
* @return Validatable
*/
public function rule(string $ruleName, array $arguments = []): Validatable
{
foreach ($this->rulesNamespaces as $namespace) {
$className = sprintf('%s\\%s', $namespace, ucfirst($ruleName));
if (!class_exists($className)) {
continue;
}
$reflection = new ReflectionClass($className);
if (!$reflection->isSubclassOf(Validatable::class)) {
throw new ComponentException(sprintf('"%s" is not a valid respect rule', $className));
}
return $reflection->newInstanceArgs($arguments);
return $this->createReflectionClass($className, Validatable::class)->newInstanceArgs($arguments);
}
throw new ComponentException(sprintf('"%s" is not a valid rule name', $ruleName));
}
/**
* Creates an exception.
*
*
* @param Validatable $validatable
* @param mixed $input
* @param array $extraParams
*
* @throws ComponentException
*
* @return ValidationException
*/
public function exception(Validatable $validatable, $input, array $extraParams = []): ValidationException
{
$reflection = new ReflectionObject($validatable);
$ruleName = $reflection->getShortName();
foreach ($this->exceptionsNamespaces as $namespace) {
$exceptionName = sprintf('%s\\%sException', $namespace, $ruleName);
if (!class_exists($exceptionName)) {
continue;
}
$name = $validatable->getName() ?: stringify($input);
$params = ['input' => $input] + $extraParams + $this->extractPropertiesValues($validatable, $reflection);
return $this->createValidationException($exceptionName, $name, $params);
}
throw new ComponentException(sprintf('Cannot find exception for "%s" rule', lcfirst($ruleName)));
}
/**
* Creates a reflection based on class name.
*
*
* @param string $name
* @param string $parentName
*
* @throws InvalidClassException
*
* @return ReflectionClass
*/
private function createReflectionClass(string $name, string $parentName): ReflectionClass
{
$reflection = new ReflectionClass($name);
if (!$reflection->isSubclassOf($parentName)) {
throw new InvalidClassException(sprintf('"%s" must be an instance of "%s"', $name, $parentName));
}
if (!$reflection->isInstantiable()) {
throw new InvalidClassException(sprintf('"%s" must be instantiable', $name));
}
return $reflection;
}
/**
* Filters namespaces.
*
* Ensure namespaces are in the right format and contain the default namespaces.
*
* @param array $namespaces
* @param array $defaultNamespaces
*
* @return array
*/
private function filterNamespaces(array $namespaces, array $defaultNamespaces): array
{
$filter = function (string $namespace): string {
return trim($namespace, '\\');
};
return array_unique(
array_merge(
array_map($filter, $namespaces),
array_map($filter, $defaultNamespaces)
)
);
}
/**
* Creates a Validation exception.
*
* @param string $exceptionName
* @param mixed $name
* @param array $params
*
* @return ValidationException
*/
private function createValidationException(string $exceptionName, $name, array $params): ValidationException
{
$exception = $this->createReflectionClass($exceptionName, ValidationException::class)->newInstance();
$exception->configure($name, $params);
if (isset($params['template'])) {
$exception->setTemplate($params['template']);
}
return $exception;
}
/**
* @param Validatable $validatable
* @param ReflectionObject $reflection
*
* @return array
*/
private function extractPropertiesValues(Validatable $validatable, ReflectionObject $reflection): array
{
$values = [];
foreach ($reflection->getProperties() as $property) {
$property->setAccessible(true);
$values[$property->getName()] = $property->getValue($validatable);
}
return $values;
}
}

View file

@ -14,7 +14,9 @@ declare(strict_types=1);
namespace Respect\Validation\Rules;
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\Factory;
use Respect\Validation\Validatable;
use Respect\Validation\Validator;
abstract class AbstractRule implements Validatable
{
@ -31,6 +33,7 @@ abstract class AbstractRule implements Validatable
if ($this->validate($input)) {
return true;
}
throw $this->reportError($input);
}
@ -46,20 +49,7 @@ abstract class AbstractRule implements Validatable
public function reportError($input, array $extraParams = [])
{
$exception = $this->createException();
$name = $this->name ?: ValidationException::stringify($input);
$params = array_merge(
get_class_vars(__CLASS__),
get_object_vars($this),
$extraParams,
compact('input')
);
$exception->configure($name, $params);
if (!is_null($this->template)) {
$exception->setTemplate($this->template);
}
return $exception;
return Factory::getDefaultInstance()->exception($this, $input, $extraParams);
}
public function setName($name)
@ -75,13 +65,4 @@ abstract class AbstractRule implements Validatable
return $this;
}
protected function createException()
{
$currentFqn = get_called_class();
$exceptionFqn = str_replace('\\Rules\\', '\\Exceptions\\', $currentFqn);
$exceptionFqn .= 'Exception';
return new $exceptionFqn();
}
}

View file

@ -161,41 +161,6 @@ use Respect\Validation\Rules\Key;
*/
class Validator extends AllOf
{
protected static $factory;
/**
* @return Factory
*/
protected static function getFactory()
{
if (!static::$factory instanceof Factory) {
static::$factory = new Factory();
}
return static::$factory;
}
/**
* @param Factory $factory
*/
public static function setFactory($factory): void
{
static::$factory = $factory;
}
/**
* @param string $rulePrefix
* @param bool $prepend
*/
public static function with($rulePrefix, $prepend = false): void
{
if (false === $prepend) {
self::getFactory()->appendRulePrefix($rulePrefix);
} else {
self::getFactory()->prependRulePrefix($rulePrefix);
}
}
public function check($input)
{
try {
@ -235,7 +200,7 @@ class Validator extends AllOf
public static function buildRule($ruleSpec, $arguments = [])
{
try {
return static::getFactory()->rule($ruleSpec, $arguments);
return Factory::getDefaultInstance()->rule($ruleSpec, $arguments);
} catch (\Exception $exception) {
throw new ComponentException($exception->getMessage(), $exception->getCode(), $exception);
}
@ -252,11 +217,6 @@ class Validator extends AllOf
return $this->addRule(static::buildRule($method, $arguments));
}
protected function createException()
{
return new AllOfException();
}
/**
* Create instance validator.
*

View file

@ -0,0 +1,20 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Test\Exceptions;
use Respect\Validation\Exceptions\ValidationException;
final class StubException extends ValidationException
{
}

View file

@ -0,0 +1,20 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Test\Rules;
use Respect\Validation\Validatable;
abstract class AbstractClass implements Validatable
{
}

View file

@ -0,0 +1,18 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Test\Rules;
final class Invalid
{
}

View file

@ -0,0 +1,57 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Test\Rules;
use function array_shift;
use Respect\Validation\Rules\AbstractRule;
/**
* Stub to help testing rules.
*
* @author Henrique Moody <henriquemoody@gmail.com>
*
* @since 2.0.0
*/
final class Stub extends AbstractRule
{
/**
* @var array
*/
public $validations;
/**
* @var array
*/
public $inputs;
/**
* Initializes the rule.
*
* @param bool[] ...$validations
*/
public function __construct(bool ...$validations)
{
$this->validations = $validations;
}
/**
* {@inheritdoc}
*/
public function validate($input): bool
{
$this->inputs[] = $input;
return (bool) array_shift($validations);
}
}

View file

@ -0,0 +1,27 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Test\Rules;
use Respect\Validation\Rules\AbstractRule;
final class Valid extends AbstractRule
{
/**
* {@inheritdoc}
*/
public function validate($input): bool
{
return true;
}
}

View file

@ -14,111 +14,210 @@ declare(strict_types=1);
namespace Respect\Validation;
use PHPUnit\Framework\TestCase;
use Respect\Validation\Exceptions\ComponentException;
use Respect\Validation\Exceptions\EqualsException;
use Respect\Validation\Exceptions\InvalidClassException;
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\Rules\Equals;
use Respect\Validation\Rules\Uppercase;
use Respect\Validation\Test\Exceptions\StubException;
use Respect\Validation\Test\Rules\AbstractClass;
use Respect\Validation\Test\Rules\Invalid;
use Respect\Validation\Test\Rules\Stub;
use Respect\Validation\Test\Rules\Valid;
use function sprintf;
/**
* @covers \Respect\Validation\Factory
*/
class FactoryTest extends TestCase
final class FactoryTest extends TestCase
{
public function testShouldHaveRulePrefixesByDefault(): void
{
$factory = new Factory();
private const TEST_RULES_NAMESPACE = 'Respect\\Validation\\Test\\Rules';
private const TEST_EXCEPTIONS_NAMESPACE = 'Respect\\Validation\\Test\\Exceptions';
self::assertEquals(['Respect\\Validation\\Rules\\'], $factory->getRulePrefixes());
/**
* @test
*/
public function shouldCreateARuleByNameBasedOnNamespace(): void
{
$factory = new Factory([self::TEST_RULES_NAMESPACE], []);
self::assertInstanceOf(Valid::class, $factory->rule('valid'));
}
/**
* @dataProvider provideRulePrefixes
* @test
*/
public function testShouldBeAbleToAppendANewPrefix($namespace, $expectedNamespace): void
public function shouldLookUpToAllNamespacesUntilRuleIsFound(): void
{
$factory = new Factory();
$factory->appendRulePrefix($namespace);
$factory = new Factory([__NAMESPACE__, self::TEST_RULES_NAMESPACE], []);
$currentRulePrefixes = $factory->getRulePrefixes();
self::assertSame(
$expectedNamespace,
array_pop($currentRulePrefixes),
'Appended namespace rule was not found as expected into the prefix list.'.PHP_EOL.
sprintf(
'Appended "%s", current list is '.PHP_EOL.'%s',
$namespace,
implode(PHP_EOL, $factory->getRulePrefixes())
)
);
self::assertInstanceOf(Valid::class, $factory->rule('valid'));
}
/**
* @dataProvider provideRulePrefixes
* @test
*/
public function testShouldBeAbleToPrependANewRulePrefix($namespace, $expectedNamespace): void
public function shouldDefineConstructorArgumentsWhenCreatingARule(): void
{
$factory = new Factory();
$factory->prependRulePrefix($namespace);
$constructorArguments = [true, false, true, false];
$currentRulePrefixes = $factory->getRulePrefixes();
$factory = new Factory([self::TEST_RULES_NAMESPACE], []);
$rule = $factory->rule('stub', $constructorArguments);
self::assertContains(
$expectedNamespace,
array_shift($currentRulePrefixes),
'Prepended namespace rule was not found as expected into the prefix list.'.PHP_EOL.
sprintf(
'Prepended "%s", current list is '.PHP_EOL.'%s',
$namespace,
implode(PHP_EOL, $factory->getRulePrefixes())
)
);
self::assertSame($constructorArguments, $rule->validations);
}
public function provideRulePrefixes()
/**
* @test
*/
public function shouldThrowsAnExceptionWhenRuleIsInvalid(): void
{
return [
'Namespace with trailing separator' => [
'namespace' => 'My\\Validation\\Rules\\',
'expected' => 'My\\Validation\\Rules\\',
],
'Namespace without trailing separator' => [
'namespace' => 'My\\Validation\\Rules',
'expected' => 'My\\Validation\\Rules\\',
],
$factory = new Factory([self::TEST_RULES_NAMESPACE], []);
$this->expectException(InvalidClassException::class);
$this->expectExceptionMessage(sprintf('"%s" must be an instance of "%s"', Invalid::class, Validatable::class));
$factory->rule('invalid');
}
/**
* @test
*/
public function shouldThrowsAnExceptionWhenRuleIsNotInstantiable(): void
{
$factory = new Factory([self::TEST_RULES_NAMESPACE], []);
$this->expectException(InvalidClassException::class);
$this->expectExceptionMessage(sprintf('"%s" must be instantiable', AbstractClass::class));
$factory->rule('abstractClass');
}
/**
* @test
*/
public function shouldThrowsAnExceptionWhenRuleIsNotFound(): void
{
$factory = new Factory([self::TEST_RULES_NAMESPACE], []);
$this->expectException(ComponentException::class);
$this->expectExceptionMessage('"notFoundRule" is not a valid rule name');
$factory->rule('notFoundRule');
}
/**
* @test
*/
public function shouldCreateExceptionBasedOnRule(): void
{
$factory = new Factory([], [self::TEST_EXCEPTIONS_NAMESPACE]);
$rule = new Stub();
$input = 2;
self::assertInstanceOf(StubException::class, $factory->exception($rule, $input));
}
/**
* @test
*/
public function shouldLookUpToAllNamespacesUntilExceptionIsCreated(): void
{
$factory = new Factory([], [__NAMESPACE__, self::TEST_EXCEPTIONS_NAMESPACE]);
$rule = new Stub();
$input = 2;
self::assertInstanceOf(StubException::class, $factory->exception($rule, $input));
}
/**
* @test
*/
public function shouldThrowAnExceptionWhenExceptionIsNotFound(): void
{
$factory = new Factory([], []);
$this->expectException(ComponentException::class);
$this->expectExceptionMessage('Cannot find exception for "stub" rule');
$factory->exception(new Stub(), 'foo');
}
/**
* @test
*/
public function shouldSetInputAsParameterOfCreatedException(): void
{
$factory = new Factory([], [self::TEST_EXCEPTIONS_NAMESPACE]);
$rule = new Stub();
$input = 2;
$exception = $factory->exception($rule, $input);
self::assertSame($input, $exception->getParam('input'));
}
/**
* @test
*/
public function shouldPassPropertiesToCreatedException(): void
{
$factory = new Factory([], [self::TEST_EXCEPTIONS_NAMESPACE]);
$validations = [true, false, true, true];
$rule = new Stub(...$validations);
$input = 2;
$exception = $factory->exception($rule, $input);
self::assertSame($validations, $exception->getParam('validations'));
}
/**
* @test
*/
public function shouldSetTemplateWhenTemplateKeyIsDefined(): void
{
$factory = new Factory([], [self::TEST_EXCEPTIONS_NAMESPACE]);
$extraParams = [
'template' => 'This is my template',
];
}
public function testShouldCreateARuleByName(): void
{
$factory = new Factory();
$validations = [true, false, true, true];
$rule = new Stub(...$validations);
$input = 2;
self::assertInstanceOf(Uppercase::class, $factory->rule('uppercase'));
}
$exception = $factory->exception($rule, $input, $extraParams);
public function testShouldDefineConstructorArgumentsWhenCreatingARule(): void
{
$factory = new Factory();
$rule = $factory->rule('dateTime', ['Y-m-d']);
self::assertEquals('Y-m-d', $rule->format);
self::assertSame($extraParams['template'], $exception->getTemplate());
}
/**
* @expectedException \Respect\Validation\Exceptions\ComponentException
* @expectedExceptionMessage "uterere" is not a valid rule name
* @test
*/
public function testShouldThrowsAnExceptionWhenRuleNameIsNotValid(): void
public function shouldAlwaysReturnTheSameDefaultInstance(): void
{
$factory = new Factory();
$factory->rule('uterere');
self::assertSame(Factory::getDefaultInstance(), Factory::getDefaultInstance());
}
/**
* @expectedException \Respect\Validation\Exceptions\ComponentException
* @expectedExceptionMessage "Respect\Validation\Exceptions\AgeException" is not a valid respect rule
* @test
*/
public function testShouldThrowsAnExceptionWhenRuleIsNotInstanceOfRuleInterface(): void
public function shouldBeAbleToOverwriteDefaultInstance(): void
{
$factory = new Factory();
$factory->appendRulePrefix('Respect\\Validation\\Exceptions\\');
$factory->rule('AgeException');
$factory = new Factory([], []);
$defaultInstance = Factory::getDefaultInstance();
Factory::setDefaultInstance($factory);
self::assertSame($factory, Factory::getDefaultInstance());
Factory::setDefaultInstance($defaultInstance);
}
}

View file

@ -126,63 +126,6 @@ class AbstractRuleTest extends TestCase
$abstractRuleMock->check($input);
}
/**
* @covers \Respect\Validation\Rules\AbstractRule::reportError
* @covers \Respect\Validation\Rules\AbstractRule::createException
*/
public function testShouldCreateExceptionBasedOnTheCurrentClassName()
{
if (defined('HHVM_VERSION')) {
return $this->markTestSkipped('If you are a HHVM user, and you are in the mood, please fix it');
}
$exceptionMock = $this
->getMockBuilder(ValidationException::class)
->setMockClassName('MockRule1Exception')
->getMock();
$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->setMockClassName('MockRule1')
->getMockForAbstractClass();
$exception = $abstractRuleMock->reportError('something');
self::assertInstanceOf(get_class($exceptionMock), $exception);
}
/**
* @covers \Respect\Validation\Rules\AbstractRule::reportError
* @covers \Respect\Validation\Rules\AbstractRule::setTemplate
*/
public function testShouldUseDefinedTemplateOnCreatedException(): void
{
$template = 'This is my template';
$exceptionMock = $this
->getMockBuilder(ValidationException::class)
->setMethods(['setTemplate'])
->getMock();
$exceptionMock
->expects($this->once())
->method('setTemplate')
->with($template);
$abstractRuleMock = $this
->getMockBuilder(AbstractRule::class)
->setMethods(['createException'])
->getMockForAbstractClass();
$abstractRuleMock
->expects($this->once())
->method('createException')
->will($this->returnValue($exceptionMock));
$abstractRuleMock->setTemplate($template);
$abstractRuleMock->reportError('something');
}
/**
* @covers \Respect\Validation\Rules\AbstractRule::setTemplate
*/