我的目标是建立自定义验证程序并使用PHPUnit对其进行测试。
PasswordComplexity.php
<?php
namespace App\Components\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Regex;
/**
* Class Password
* @package App\Components\Validator\Constraint
* @Annotation
*/
class PasswordComplexity extends Regex
{
public $message = 'The password "{{string}}" does not meet the password policy requirements.';
public $pattern = [
'/.{8,}/',
'/\d+/',
'/[a-z]+/',
'/[A-Z]+/',
'/[!@#$%\-_*+=]+/'
];
/**
* {@inheritdoc}
*/
public function getRequiredOptions()
{
return [];
}
}
PasswordComplexityValidator.php
<?php
declare(strict_types=1);
namespace App\Components\Validator\Constraint;
use Symfony\Component\Validator\Constraints\RegexValidator;
class PasswordComplexityValidator extends RegexValidator
{
}
PasswordComplexityValidatorTest.php
<?php
declare(strict_types=1);
namespace App\Tests\Components\Validator\Constraint;
use App\Components\Validator\Constraint\PasswordComplexity;
use App\Components\Validator\Constraint\PasswordComplexityValidator;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Context\ExecutionContext;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Violation\ConstraintViolationBuilderInterface;
class PasswordComplexityValidatorTest extends TestCase
{
public function testRequiredOptions()
{
$validator = new PasswordComplexity();
$this->assertEquals([], $validator->getRequiredOptions());
}
/**
* @dataProvider validPasswordProvider
*/
public function testValidation($value)
{
$constraint = new PasswordComplexity();
/** @var ExecutionContextInterface|MockObject $context */
$context = $this->getMockExecutionContext();
$context->expects($this->never())->method('buildViolation');
$validator = new PasswordComplexityValidator();
$validator->initialize($context);
$validator->validate($value, $constraint);
}
/**
* @dataProvider invalidPasswordProvider
*/
public function testValidationFail($value)
{
$constraint = new PasswordComplexity();
/** @var ExecutionContextInterface|MockObject $context */
$context = $this->getMockExecutionContext();
$context->expects($this->once())
->method('buildViolation')
->with($constraint->message)
->willReturn($this->getMockConstraintViolationBuilder());
$validator = new PasswordComplexityValidator();
$validator->initialize($context);
$validator->validate($value, $constraint);
}
public function validPasswordProvider()
{
return [
['jXb8p$cn'],
['!MC6NcuS'],
['!3%Sy6iF'],
['XyiWmw2#'],
['r@5e#hSY'],
];
}
public function invalidPasswordProvider()
{
return [ // conditions not meet:
['YQ(GJ)&'], // at least 8 characters
['LuAqA=uX'], // at least 1 digit (0 to 9)
['{OG>:@I1'], // at least 1 small case letter
[']su-(+\a'], // at least 1 upper case letter
['CJuCyAGc'], // at least 1 special character
];
}
private function getMockExecutionContext()
{
$context = $this->getMockBuilder(ExecutionContext::class)
->disableOriginalConstructor()
->getMock();
return $context;
}
private function getMockConstraintViolationBuilder()
{
$constraintViolationBuilder = $this->getMockBuilder(ConstraintViolationBuilderInterface::class)->getMock();
$constraintViolationBuilder
->method('setParameter')
->willReturn($constraintViolationBuilder);
$constraintViolationBuilder
->method('setCode')
->willReturn($constraintViolationBuilder);
$constraintViolationBuilder
->method('addViolation');
return $constraintViolationBuilder;
}
我有以下错误:
这是10个错误:
\ Tests \ Components \ Validator \ Constraint \ PasswordComplexityValidatorTest :: testValidation与数据集#0('jXb8p $ cn') preg_match()期望参数1为字符串,给定数组
我不知道如何将数组样本传递给验证器。
答案 0 :(得分:0)
我已经解决了这个问题。
我的正则表达式模式与示例数据不匹配,更改为:
public function invalidPasswordProvider()
{
return [ // conditions not meet:
['J#$j#2'], // at least 8 characters
['LuAqA=uX'], // at least 1 digit (0 to 9)
['$OG3W4I1'], // at least 1 small case letter
['3su-a+aa'], // at least 1 upper case letter
['CJuC$AGc'], // at least 1 special character
];
}
Pattern变量已从PasswordComplexity.php中删除
public $pattern = [
'/.{8,}/',
'/\d+/',
'/[a-z]+/',
'/[A-Z]+/',
'/[!@#$%\-_*+=]+/'
];
PasswordComplexityValidator.php已充满验证功能和所有必要数据:
<?php
declare(strict_types=1);
namespace App\Components\Validator\Constraint;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\RegexValidator;
class PasswordComplexityValidator extends RegexValidator
{
const PASS_REQ_1 = '/.{8,}/'; // at least 8 characters
const PASS_REQ_2 = '/\d+/'; // at least 1 digit (0 to 9)
const PASS_REQ_3 = '/[a-z]+/'; // at least 1 small case letter
const PASS_REQ_4 = '/[A-Z]+/'; // at least 1 upper case letter
const PASS_REQ_5 = '/[!@#$%\-_*+=]+/'; // at least 1 special character (e.g.: !@#$%-_*+=)
public static $patterns = [
self::PASS_REQ_1,
self::PASS_REQ_2,
self::PASS_REQ_3,
self::PASS_REQ_4,
self::PASS_REQ_5,
];
public function validate($password, Constraint $constraint)
{
foreach (self::$patterns as $pattern) {
if (!preg_match($pattern, $password, $matches))
{
$this->context
->buildViolation($constraint->message)
->setParameter('{{ string }}', $password)
->addViolation();
}
}
}
}
也更改了
/**
* @dataProvider invalidPasswordProvider
*/
public function testValidationFail($value)
{
$constraint = new PasswordComplexity();
/** @var ExecutionContextInterface|MockObject $context */
$context = $this->getMockExecutionContext();
$context->expects($this->once())
到
$context->expects($this->atLeast(1))
如果密码不匹配多个正则表达式,则进行测试。
测试通过了,我觉得现在一切都应该正常了。
关于, J