From b158dcf32f5ab0df0a4b53178181b1e61136dcaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mart=C3=ADnez?= Date: Sat, 21 Oct 2017 03:25:22 +0200 Subject: [PATCH] Fix AcountManagementTest unit test to not randomly fail due to execution time --- .../Customer/Model/AccountManagement.php | 75 +++++++++++-------- .../Test/Unit/Model/AccountManagementTest.php | 64 ++++++++++++++-- 2 files changed, 98 insertions(+), 41 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index b7b099ec45232..a48222692bea0 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -12,16 +12,17 @@ use Magento\Customer\Api\Data\AddressInterface; use Magento\Customer\Api\Data\CustomerInterface; use Magento\Customer\Api\Data\ValidationResultsInterfaceFactory; -use Magento\Customer\Model\EmailNotificationInterface; use Magento\Customer\Helper\View as CustomerViewHelper; use Magento\Customer\Model\Config\Share as ConfigShare; use Magento\Customer\Model\Customer as CustomerModel; +use Magento\Customer\Model\Customer\CredentialsValidator; use Magento\Customer\Model\Metadata\Validator; use Magento\Eav\Model\Validator\Attribute\Backend; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\App\Area; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ObjectManager; +use Magento\Framework\DataObjectFactory as ObjectFactory; use Magento\Framework\Encryption\EncryptorInterface as Encryptor; use Magento\Framework\Encryption\Helper\Security; use Magento\Framework\Event\ManagerInterface; @@ -30,23 +31,22 @@ use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\InvalidEmailOrPasswordException; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\MailException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\State\ExpiredException; use Magento\Framework\Exception\State\InputMismatchException; use Magento\Framework\Exception\State\InvalidTransitionException; -use Magento\Framework\DataObjectFactory as ObjectFactory; use Magento\Framework\Exception\State\UserLockedException; -use Magento\Framework\Registry; -use Magento\Store\Model\ScopeInterface; -use Psr\Log\LoggerInterface as PsrLogger; -use Magento\Framework\Exception\MailException; +use Magento\Framework\Intl\DateTimeFactory; use Magento\Framework\Mail\Template\TransportBuilder; use Magento\Framework\Math\Random; use Magento\Framework\Reflection\DataObjectProcessor; +use Magento\Framework\Registry; use Magento\Framework\Stdlib\DateTime; use Magento\Framework\Stdlib\StringUtils as StringHelper; +use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; -use Magento\Customer\Model\Customer\CredentialsValidator; +use Psr\Log\LoggerInterface as PsrLogger; /** * Handle various customer account actions @@ -293,6 +293,11 @@ class AccountManagement implements AccountManagementInterface */ private $credentialsValidator; + /** + * @var DateTimeFactory + */ + private $dateTimeFactory; + /** * @param CustomerFactory $customerFactory * @param ManagerInterface $eventManager @@ -318,6 +323,7 @@ class AccountManagement implements AccountManagementInterface * @param ObjectFactory $objectFactory * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter * @param CredentialsValidator|null $credentialsValidator + * @param DateTimeFactory $dateTimeFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -344,7 +350,8 @@ public function __construct( CustomerModel $customerModel, ObjectFactory $objectFactory, ExtensibleDataObjectConverter $extensibleDataObjectConverter, - CredentialsValidator $credentialsValidator = null + CredentialsValidator $credentialsValidator = null, + DateTimeFactory $dateTimeFactory = null ) { $this->customerFactory = $customerFactory; $this->eventManager = $eventManager; @@ -369,8 +376,9 @@ public function __construct( $this->customerModel = $customerModel; $this->objectFactory = $objectFactory; $this->extensibleDataObjectConverter = $extensibleDataObjectConverter; - $this->credentialsValidator = $credentialsValidator ?: ObjectManager::getInstance() - ->get(CredentialsValidator::class); + $this->credentialsValidator = + $credentialsValidator ?: ObjectManager::getInstance()->get(CredentialsValidator::class); + $this->dateTimeFactory = $dateTimeFactory ?: ObjectManager::getInstance()->get(DateTimeFactory::class); } /** @@ -380,7 +388,6 @@ public function __construct( */ private function getAuthentication() { - if (!($this->authentication instanceof AuthenticationInterface)) { return \Magento\Framework\App\ObjectManager::getInstance()->get( \Magento\Customer\Model\AuthenticationInterface::class @@ -613,16 +620,16 @@ protected function makeRequiredCharactersCheck($password) $return = 0; if (preg_match('/[0-9]+/', $password)) { - $counter ++; + $counter++; } if (preg_match('/[A-Z]+/', $password)) { - $counter ++; + $counter++; } if (preg_match('/[a-z]+/', $password)) { - $counter ++; + $counter++; } if (preg_match('/[^a-zA-Z0-9]+/', $password)) { - $counter ++; + $counter++; } if ($counter < $requiredNumber) { @@ -890,16 +897,14 @@ public function validate(CustomerInterface $customer) $result = $this->getEavValidator()->isValid($customerModel); if ($result === false && is_array($this->getEavValidator()->getMessages())) { - return $validationResults->setIsValid(false) - ->setMessages( - call_user_func_array( - 'array_merge', - $this->getEavValidator()->getMessages() - ) - ); + return $validationResults->setIsValid(false)->setMessages( + call_user_func_array( + 'array_merge', + $this->getEavValidator()->getMessages() + ) + ); } - return $validationResults->setIsValid(true) - ->setMessages([]); + return $validationResults->setIsValid(true)->setMessages([]); } /** @@ -949,10 +954,12 @@ public function isCustomerInStore($customerWebsiteId, $storeId) private function validateResetPasswordToken($customerId, $resetPasswordLinkToken) { if (empty($customerId) || $customerId < 0) { - throw new InputException(__( - 'Invalid value of "%value" provided for the %fieldName field.', - ['value' => $customerId, 'fieldName' => 'customerId'] - )); + throw new InputException( + __( + 'Invalid value of "%value" provided for the %fieldName field.', + ['value' => $customerId, 'fieldName' => 'customerId'] + ) + ); } if (!is_string($resetPasswordLinkToken) || empty($resetPasswordLinkToken)) { $params = ['fieldName' => 'resetPasswordLinkToken']; @@ -1178,8 +1185,8 @@ public function isResetPasswordLinkTokenExpired($rpToken, $rpTokenCreatedAt) $expirationPeriod = $this->customerModel->getResetPasswordLinkExpirationPeriod(); - $currentTimestamp = (new \DateTime())->getTimestamp(); - $tokenTimestamp = (new \DateTime($rpTokenCreatedAt))->getTimestamp(); + $currentTimestamp = $this->dateTimeFactory->create()->getTimestamp(); + $tokenTimestamp = $this->dateTimeFactory->create($rpTokenCreatedAt)->getTimestamp(); if ($tokenTimestamp > $currentTimestamp) { return true; } @@ -1215,7 +1222,9 @@ public function changeResetPasswordLinkToken($customer, $passwordLinkToken) if (is_string($passwordLinkToken) && !empty($passwordLinkToken)) { $customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId()); $customerSecure->setRpToken($passwordLinkToken); - $customerSecure->setRpTokenCreatedAt((new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT)); + $customerSecure->setRpTokenCreatedAt( + $this->dateTimeFactory->create()->format(DateTime::DATETIME_PHP_FORMAT) + ); $this->customerRepository->save($customer); } return true; @@ -1304,8 +1313,8 @@ protected function getFullCustomerObject($customer) // No need to flatten the custom attributes or nested objects since the only usage is for email templates and // object passed for events $mergedCustomerData = $this->customerRegistry->retrieveSecureData($customer->getId()); - $customerData = $this->dataProcessor - ->buildOutputDataArray($customer, \Magento\Customer\Api\Data\CustomerInterface::class); + $customerData = + $this->dataProcessor->buildOutputDataArray($customer, \Magento\Customer\Api\Data\CustomerInterface::class); $mergedCustomerData->addData($customerData); $mergedCustomerData->setData('name', $this->customerViewHelper->getCustomerName($customer)); return $mergedCustomerData; diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index de9c0460ad29e..34662eecc0c1c 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -10,6 +10,7 @@ use Magento\Customer\Model\EmailNotificationInterface; use Magento\Framework\App\Area; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Intl\DateTimeFactory; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Store\Model\ScopeInterface; @@ -114,6 +115,11 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase */ protected $emailNotificationMock; + /** + * @var DateTimeFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $dateTimeFactory; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -163,6 +169,8 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); + $this->dateTimeFactory = $this->createMock(DateTimeFactory::class); + $this->objectManagerHelper = new ObjectManagerHelper($this); $this->accountManagement = $this->objectManagerHelper->getObject( \Magento\Customer\Model\AccountManagement::class, @@ -190,6 +198,7 @@ protected function setUp() 'customerModel' => $this->customer, 'objectFactory' => $this->objectFactory, 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverter, + 'dateTimeFactory' => $this->dateTimeFactory, ] ); $reflection = new \ReflectionClass(get_class($this->accountManagement)); @@ -552,6 +561,8 @@ public function testCreateAccountWithoutPassword() $customerEmail = 'email@email.com'; $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu'; + $datetime = $this->prepareDateTimeFactory(); + $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class) ->disableOriginalConstructor() ->getMock(); @@ -624,7 +635,9 @@ public function testCreateAccountWithoutPassword() ->method('setRpToken') ->with($newLinkToken); $customerSecure->expects($this->any()) - ->method('setRpTokenCreatedAt'); + ->method('setRpTokenCreatedAt') + ->with($datetime) + ->willReturnSelf(); $customerSecure->expects($this->any()) ->method('getPasswordHash') ->willReturn(null); @@ -756,6 +769,8 @@ public function testCreateAccountWithPassword() $minPasswordLength = 5; $minCharacterSetsNum = 2; + $datetime = $this->prepareDateTimeFactory(); + $this->scopeConfig->expects($this->any()) ->method('getValue') ->willReturnMap( @@ -865,7 +880,9 @@ public function testCreateAccountWithPassword() ->method('setRpToken') ->with($newLinkToken); $customerSecure->expects($this->any()) - ->method('setRpTokenCreatedAt'); + ->method('setRpTokenCreatedAt') + ->with($datetime) + ->willReturnSelf(); $customerSecure->expects($this->any()) ->method('getPasswordHash') ->willReturn($hash); @@ -995,7 +1012,7 @@ protected function prepareInitiatePasswordReset($email, $templateIdentifier, $se { $websiteId = 1; - $dateTime = date(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT); + $datetime = $this->prepareDateTimeFactory(); $customerData = ['key' => 'value']; $customerName = 'Customer Name'; @@ -1047,7 +1064,7 @@ protected function prepareInitiatePasswordReset($email, $templateIdentifier, $se ->willReturnSelf(); $this->customerSecure->expects($this->any()) ->method('setRpTokenCreatedAt') - ->with($dateTime) + ->with($datetime) ->willReturnSelf(); $this->customerSecure->expects($this->any()) ->method('addData') @@ -1257,18 +1274,20 @@ private function reInitModel() ->method('getRpToken') ->willReturn('newStringToken'); - $date = date('Y-m-d', strtotime('-1 year')); + $pastDateTime = '2016-10-25 00:00:00'; $this->customerSecure ->expects($this->any()) ->method('getRpTokenCreatedAt') - ->willReturn($date); + ->willReturn($pastDateTime); $this->customer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class) ->disableOriginalConstructor() ->setMethods(['getResetPasswordLinkExpirationPeriod']) ->getMock(); + $this->prepareDateTimeFactory(); + $this->objectManagerHelper = new ObjectManagerHelper($this); $this->accountManagement = $this->objectManagerHelper->getObject( \Magento\Customer\Model\AccountManagement::class, @@ -1277,6 +1296,7 @@ private function reInitModel() 'customerRegistry' => $this->customerRegistry, 'customerRepository' => $this->customerRepository, 'customerModel' => $this->customer, + 'dateTimeFactory' => $this->dateTimeFactory, ] ); $reflection = new \ReflectionClass(get_class($this->accountManagement)); @@ -1320,7 +1340,7 @@ public function testChangePassword() ->with(null); $customerSecure->expects($this->once()) ->method('setRpTokenCreatedAt') - ->with(null); + ->willReturnSelf(); $customerSecure->expects($this->any()) ->method('getPasswordHash') ->willReturn($passwordHash); @@ -1586,6 +1606,8 @@ public function testCreateAccountWithPasswordHashWithCustomerAddresses() $storeId = 1; $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; + $this->prepareDateTimeFactory(); + //Handle store $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock(); $store->expects($this->any()) @@ -1630,7 +1652,7 @@ public function testCreateAccountWithPasswordHashWithCustomerAddresses() ->expects($this->any()) ->method("getId") ->willReturn($customerId); - //Return Customer from customer repositoryå + //Return Customer from customer repository $this->customerRepository ->expects($this->atLeastOnce()) ->method('save') @@ -1673,4 +1695,30 @@ public function testCreateAccountWithPasswordHashWithCustomerAddresses() $this->assertSame($customer, $this->accountManagement->createAccountWithPasswordHash($customer, $hash)); } + + /** + * @return string + */ + private function prepareDateTimeFactory() + { + $dateTime = '2017-10-25 18:57:08'; + $timestamp = '1508983028'; + $dateTimeMock = $this->createMock(\DateTime::class); + $dateTimeMock->expects($this->any()) + ->method('format') + ->with(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT) + ->willReturn($dateTime); + + $dateTimeMock + ->expects($this->any()) + ->method('getTimestamp') + ->willReturn($timestamp); + + $this->dateTimeFactory + ->expects($this->any()) + ->method('create') + ->willReturn($dateTimeMock); + + return $dateTime; + } }