phpunit update

This commit is contained in:
Yuri Kuznetsov
2025-07-08 20:57:16 +03:00
parent 7b30ba59dd
commit a468c42347
25 changed files with 1207 additions and 942 deletions

View File

@@ -58,7 +58,7 @@
"psr/clock": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"phpunit/phpunit": "^11.5",
"phpstan/phpstan": "^2.1"
},
"suggest": {

713
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -31,6 +31,8 @@ namespace tests\unit;
use Espo\Core\Container;
use PHPUnit\Framework\MockObject\MockBuilder;
use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
@@ -46,7 +48,7 @@ class ContainerMocker
public function create(array $serviceMap) : Container
{
$container = $this->test->getMockBuilder(Container::class)->disableOriginalConstructor()->getMock();
$container = (new MockBuilder($this->test, Container::class))->disableOriginalConstructor()->getMock();
$map = $serviceMap;
@@ -67,19 +69,19 @@ class ContainerMocker
}
$container
->expects($this->test->any())
->expects(new AnyInvokedCountMatcher)
->method('get')
->will($this->test->returnValueMap($valueMap));
->willReturnMap($valueMap);
$container
->expects($this->test->any())
->expects(new AnyInvokedCountMatcher)
->method('has')
->will($this->test->returnValueMap($hasMap));
->willReturnMap($hasMap);
$container
->expects($this->test->any())
->expects(new AnyInvokedCountMatcher)
->method('getClass')
->will($this->test->returnValueMap($classMap));
->willReturnMap($classMap);
return $container;
}

View File

@@ -29,12 +29,12 @@
namespace tests\unit\Espo\Core\Field\Currency;
use Espo\Core\{
Currency\ConfigDataProvider as CurrencyConfigDataProvider,
Utils\Config,
};
use Espo\Core\Currency\ConfigDataProvider as CurrencyConfigDataProvider;
use Espo\Core\Utils\Config;
use PHPUnit\Framework\TestCase;
use RuntimeException;
class CurrencyConfigDataProviderTest extends \PHPUnit\Framework\TestCase
class CurrencyConfigDataProviderTest extends TestCase
{
protected function setUp() : void
{
@@ -97,19 +97,28 @@ class CurrencyConfigDataProviderTest extends \PHPUnit\Framework\TestCase
public function testCurrencyRate1()
{
$invokedCount = $this->exactly(2);
$this->config
->expects($this->exactly(2))
->expects($invokedCount)
->method('get')
->withConsecutive(
['currencyRates'],
['currencyList'],
)
->willReturnOnConsecutiveCalls(
[
'EUR' => 1.2,
],
['USD', 'EUR'],
);
->willReturnCallback(function ($param) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('currencyRates', $param);
return [
'EUR' => 1.2,
];
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('currencyList', $param);
return ['USD', 'EUR'];
}
throw new RuntimeException();
});
$result = $this->provider->getCurrencyRate('EUR');
@@ -118,19 +127,28 @@ class CurrencyConfigDataProviderTest extends \PHPUnit\Framework\TestCase
public function testCurrencyRate2()
{
$invokedCount = $this->exactly(2);
$this->config
->expects($this->exactly(2))
->expects($invokedCount)
->method('get')
->withConsecutive(
['currencyRates'],
['currencyList'],
)
->willReturnOnConsecutiveCalls(
[
'EUR' => 1.2,
],
['USD', 'EUR'],
);
->willReturnCallback(function ($param) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('currencyRates', $param);
return [
'EUR' => 1.2,
];
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('currencyList', $param);
return ['USD', 'EUR'];
}
throw new RuntimeException();
});
$result = $this->provider->getCurrencyRate('USD');

View File

@@ -51,7 +51,7 @@ class EvaluatorTest extends TestCase
*/
private $evaluator;
protected function setUp() : void
protected function setUp(): void
{
$log = $this->createMock(Log::class);
$entityManager = $this->createMock(EntityManager::class);

View File

@@ -29,21 +29,18 @@
namespace tests\unit\Espo\Core\Select\Applier\Appliers;
use Espo\Core\{
Select\AccessControl\Applier as AccessControlFilterApplier,
Select\SelectManager,
Select\AccessControl\FilterFactory as AccessControlFilterFactory,
Select\AccessControl\FilterResolverFactory as AccessControlFilterResolverFactory,
Select\AccessControl\FilterResolver,
Select\AccessControl\Filter as AccessControlFilter,
};
use Espo\Core\Select\AccessControl\Applier as AccessControlFilterApplier;
use Espo\Core\Select\AccessControl\Filter as AccessControlFilter;
use Espo\Core\Select\AccessControl\FilterFactory as AccessControlFilterFactory;
use Espo\Core\Select\AccessControl\FilterResolver;
use Espo\Core\Select\AccessControl\FilterResolverFactory as AccessControlFilterResolverFactory;
use Espo\Core\Select\SelectManager;
use Espo\{
ORM\Query\SelectBuilder as QueryBuilder,
Entities\User,
};
use Espo\Entities\User;
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
use PHPUnit\Framework\TestCase;
class AccessControlFilterApplierTest extends \PHPUnit\Framework\TestCase
class AccessControlFilterApplierTest extends TestCase
{
protected function setUp() : void
{
@@ -141,14 +138,10 @@ class AccessControlFilterApplierTest extends \PHPUnit\Framework\TestCase
$this->filterFactory
->expects($this->exactly(2))
->method('create')
->withConsecutive(
[$this->entityType, $this->user, 'mandatory'],
[$this->entityType, $this->user, $filterName],
)
->willReturnOnConsecutiveCalls(
$this->mandatoryFilter,
$this->filter
);
->willReturnMap([
[$this->entityType, $this->user, 'mandatory', $this->mandatoryFilter],
[$this->entityType, $this->user, $filterName, $this->filter],
]);
$this->filter
->expects($this->once())

View File

@@ -208,13 +208,22 @@ class TextFilterApplierTest extends TestCase
->method('where')
->with(OrGroup::fromRaw($expectedWhere));
$c = $this->exactly(2);
$this->queryBuilder
->expects($this->exactly(2))
->expects($c)
->method('leftJoin')
->withConsecutive(
['link1'],
['link2']
);
->willReturnCallback(function ($link) use ($c) {
if ($c->numberOfInvocations() === 1) {
$this->assertEquals('link1', $link);
}
if ($c->numberOfInvocations() === 2) {
$this->assertEquals('link2', $link);
}
return $this->queryBuilder;
});
$this->queryBuilder
->expects($this->once())

View File

@@ -113,20 +113,25 @@ class FilterFactoryTest extends TestCase
);
$this->metadata
->expects(self::any())
->method('get')
->withConsecutive(
[[
'selectDefs',
$entityType,
'boolFilterClassNameMap',
'badName',
]],
[['app', 'select', 'boolFilterClassNameMap', 'badName']],
)
->willReturnOnConsecutiveCalls(
null,
null
);
->willReturnMap([
[
[
'selectDefs',
$entityType,
'boolFilterClassNameMap',
'badName',
],
null,
null
],
[
['app', 'select', 'boolFilterClassNameMap', 'badName'],
null,
null
],
]);
$this->assertFalse(
$this->factory->has($entityType, 'badName')

View File

@@ -114,15 +114,12 @@ class CheckerTest extends TestCase
]);
$this->entity
->expects(self::any())
->method('hasAttribute')
->withConsecutive(
['test1'],
['test2']
)
->willReturnOnConsecutiveCalls(
true,
true
);
->willReturnMap([
['test1', true],
['test2', true],
]);
$this->entity
->expects($this->once())
@@ -158,13 +155,11 @@ class CheckerTest extends TestCase
]);
$this->entity
->expects(self::any())
->method('hasAttribute')
->withConsecutive(
['test1']
)
->willReturnOnConsecutiveCalls(
false
);
->willReturnMap([
['test1', false]
]);
$this->expectException(BadRequest::class);

View File

@@ -42,9 +42,18 @@ use Espo\Core\Select\Where\ItemGeneralConverter;
use Espo\Core\Utils\Metadata;
use Espo\Entities\User;
use PHPUnit\Framework\TestCase;
use RuntimeException;
class ConverterFactoryTest extends \PHPUnit\Framework\TestCase
class ConverterFactoryTest extends TestCase
{
private $injectableFactory;
private $metadata;
private $user;
private $factory;
private $itemConverter;
private $dateTimeItemTransformer;
protected function setUp(): void
{
$this->injectableFactory = $this->createMock(InjectableFactory::class);
@@ -92,19 +101,16 @@ class ConverterFactoryTest extends \PHPUnit\Framework\TestCase
$bindingData1 = new BindingData();
$binder1 = new Binder($bindingData1);
$binder1
->bindInstance(User::class, $this->user);
$binder1
->for($className1)
->bindValue('$entityType', $entityType);
$binder1
->for(DefaultDateTimeItemTransformer::class)
->bindValue('$entityType', $entityType);
$bindingContainer1 = new BindingContainer($bindingData1);
$bc1 = new BindingContainer($bindingData1);
$bindingData2 = new BindingData();
@@ -112,18 +118,16 @@ class ConverterFactoryTest extends \PHPUnit\Framework\TestCase
$binder2
->bindInstance(User::class, $this->user);
$binder2
->for($className2)
->bindValue('$entityType', $entityType)
->bindInstance(DateTimeItemTransformer::class, $this->dateTimeItemTransformer);
$binder2
->for(ItemGeneralConverter::class)
->bindValue('$entityType', $entityType)
->bindInstance(DateTimeItemTransformer::class, $this->dateTimeItemTransformer);
$bindingContainer2 = new BindingContainer($bindingData2);
$bc2 = new BindingContainer($bindingData2);
$bindingData3 = new BindingData();
@@ -135,30 +139,39 @@ class ConverterFactoryTest extends \PHPUnit\Framework\TestCase
->bindValue('$entityType', $entityType)
->bindInstance(ItemConverter::class, $this->itemConverter);
$bindingContainer = new BindingContainer($bindingData3);
$bc3 = new BindingContainer($bindingData3);
$c = $this->exactly(3);
$this->injectableFactory
->expects($this->exactly(3))
->expects($c)
->method('createWithBinding')
->withConsecutive(
[
$className1,
$bindingContainer1,
],
[
$className2,
$bindingContainer2,
],
[
$className3,
$bindingContainer,
]
)
->willReturnOnConsecutiveCalls(
$this->dateTimeItemTransformer,
$this->itemConverter,
$object
);
->willReturnCallback(function ($className, $bc) use
($c, $object, $className1, $className2, $className3, $bc1, $bc2, $bc3) {
if ($c->numberOfInvocations() === 1) {
$this->assertEquals($className1, $className);
$this->assertEquals($bc1, $bc);
return $this->dateTimeItemTransformer;
}
if ($c->numberOfInvocations() === 2) {
$this->assertEquals($className2, $className);
$this->assertEquals($bc2, $bc);
return $this->itemConverter;
}
if ($c->numberOfInvocations() === 3) {
$this->assertEquals($className3, $className);
$this->assertEquals($bc3, $bc);
return $object;
}
throw new RuntimeException();
});
$resultObject = $this->factory->create($entityType, $this->user);

View File

@@ -278,12 +278,20 @@ class ConverterTest extends TestCase
],
]);
$c = $this->exactly(2);
$this->scanner
->expects($c)
->method('apply')
->withConsecutive(
[$this->isInstanceOf(QueryBuilder::class), $sqItem],
[$this->queryBuilder, $item]
);
->willReturnCallback(function ($qb, $it) use ($c, $sqItem, $item) {
if ($c->numberOfInvocations() === 1) {
$this->assertEquals($sqItem, $it);
}
if ($c->numberOfInvocations() === 2) {
$this->assertEquals($item, $it);
}
});
$whereClause = $this->converter->convert($this->queryBuilder, $item);
@@ -347,14 +355,6 @@ class ConverterTest extends TestCase
->expects($this->never())
->method('distinct');
$this->queryBuilder
->method('leftJoin')
->withConsecutive(
[
$link,
$alias,
]
);
$expected = [
'id=s' => Select::fromRaw([

View File

@@ -111,14 +111,26 @@ class ScannerTest extends TestCase
])
);
$c = $this->exactly(3);
$this->queryBuilder
->expects($this->exactly(3))
->expects($c)
->method('leftJoin')
->withConsecutive(
['link2'],
['link3'],
['link4'],
);
->willReturnCallback(function ($link) use ($c) {
if ($c->numberOfInvocations() === 1) {
$this->assertEquals('link2', $link);
}
if ($c->numberOfInvocations() === 2) {
$this->assertEquals('link3', $link);
}
if ($c->numberOfInvocations() === 3) {
$this->assertEquals('link4', $link);
}
return $this->queryBuilder;
});
/*$this->queryBuilder
->expects($this->once())

View File

@@ -210,7 +210,7 @@ class BaseTest extends TestCase
$this->assertEquals( json_decode($manifest,true), $this->reflection->invokeMethod('getManifest') );
}
public function acceptableVersions()
static public function acceptableVersions()
{
return [
['11.5.2'],
@@ -243,7 +243,7 @@ class BaseTest extends TestCase
);
}
public function unacceptableVersions()
static public function unacceptableVersions()
{
return [
['1.*',],

View File

@@ -29,16 +29,21 @@
namespace tests\unit\Espo\Core\Utils\Config;
use Espo\Core\{
Utils\Config,
Utils\Config\ConfigWriter,
Utils\Config\ConfigWriterFileManager,
Utils\Config\ConfigWriterHelper,
Utils\Config\InternalConfigHelper,
};
use Espo\Core\Utils\Config;
use Espo\Core\Utils\Config\ConfigWriter;
use Espo\Core\Utils\Config\ConfigWriterFileManager;
use Espo\Core\Utils\Config\ConfigWriterHelper;
use Espo\Core\Utils\Config\InternalConfigHelper;
use PHPUnit\Framework\TestCase;
class ConfigWriterTest extends \PHPUnit\Framework\TestCase
class ConfigWriterTest extends TestCase
{
private $fileManager;
private $config;
private $helper;
private $internalConfigHelper;
private $configWriter;
protected function setUp(): void
{
$this->fileManager = $this->createMock(ConfigWriterFileManager::class);
@@ -111,15 +116,12 @@ class ConfigWriterTest extends \PHPUnit\Framework\TestCase
->method('update');
$this->fileManager
->expects($this->any())
->method('isFile')
->withConsecutive(
[$this->configPath],
[$this->internalConfigPath],
)
->willReturnOnConsecutiveCalls(
true,
false
);
->willReturnMap([
[$this->configPath, true],
[$this->internalConfigPath, false],
]);
$this->fileManager
->expects($this->once())
@@ -129,11 +131,10 @@ class ConfigWriterTest extends \PHPUnit\Framework\TestCase
$this->fileManager
->expects($this->exactly(2))
->method('getPhpContents')
->withConsecutive(
[$this->configPath],
[$this->configPath],
)
->willReturnOnConsecutiveCalls($previousData, $previousData);
->willReturnMap([
[$this->configPath, $previousData],
[$this->configPath, $previousData],
]);
$this->configWriter->save();
}
@@ -145,12 +146,12 @@ class ConfigWriterTest extends \PHPUnit\Framework\TestCase
$this->internalConfigHelper
->method('isParamForInternalConfig')
->will(
$this->returnValueMap([
->willReturnMap(
[
['k1', false],
['k2', true],
['cacheTimestamp', false],
])
]
);
$this->helper
@@ -164,36 +165,36 @@ class ConfigWriterTest extends \PHPUnit\Framework\TestCase
->willReturn(1);
$this->fileManager
->expects(self::any())
->method('isFile')
->withConsecutive(
[$this->configPath],
[$this->internalConfigPath],
)
->willReturnOnConsecutiveCalls(
true,
true
);
->willReturnMap([
[$this->configPath, true],
[$this->internalConfigPath, true],
]);
$this->fileManager
->expects($this->exactly(4))
->method('getPhpContents')
->withConsecutive(
[$this->configPath],
[$this->internalConfigPath],
[$this->internalConfigPath],
[$this->configPath],
)
->willReturnOnConsecutiveCalls(
[],
[],
);
->willReturnMap([
[$this->configPath, []],
[$this->internalConfigPath, []],
[$this->internalConfigPath, []],
[$this->configPath, []],
]);
$this->fileManager
->method('putPhpcontents')
->withConsecutive(
[$this->internalConfigPath, ['k2' => 'v2', 'microtimeInternal' => 1.0]],
[$this->configPath, ['k1' => 'v1', 'cacheTimestamp' => 1, 'microtime' => 1.0]],
);
->expects(self::any())
->method('putPhpContents')
->willReturnMap([
[
$this->internalConfigPath,
['k2' => 'v2', 'microtimeInternal' => 1.0]
],
[
$this->configPath,
['k1' => 'v1', 'cacheTimestamp' => 1, 'microtime' => 1.0]
],
]);
$this->configWriter->save();
}

View File

@@ -29,12 +29,12 @@
namespace tests\unit\Espo\Core\Utils\File;
use PHPUnit\Framework\TestCase;
use tests\unit\ReflectionHelper;
use Espo\Core\Utils\Util;
use Espo\Core\Utils\File\Manager as FileManager;
class ManagerTest extends \PHPUnit\Framework\TestCase
class ManagerTest extends TestCase
{
/**
* @var FileManager
@@ -42,9 +42,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
private $fileManager;
protected $filesPath = 'tests/unit/testData/FileManager';
protected $cachePath = 'tests/unit/testData/cache/FileManager';
protected const CACHE_PATH = 'tests/unit/testData/cache/FileManager';
protected $reflection;
protected function setUp(): void
@@ -77,7 +75,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
public function testPutContents()
{
$testPath = $this->cachePath;
$testPath = self::CACHE_PATH;
$result= 'next value';
@@ -159,7 +157,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
public function testUnsetContents()
{
$testPath = $this->cachePath.'/unsets.json';
$testPath = self::CACHE_PATH.'/unsets.json';
$initData = '{"fields":{"someName":{"type":"varchar","maxLength":40},"someName2":{"type":"varchar","maxLength":36}}}';
$this->fileManager->putContents($testPath, $initData);
@@ -314,10 +312,10 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
$this->assertEquals($result, $this->reflection->invokeMethod('getSingleFileList', array($input, false)));
}
public function fileListSets()
static public function fileListSets()
{
return array(
array( 'Set1', array(
return [
['Set1', [
'custom',
'custom/Espo',
'custom/Espo/Custom',
@@ -325,10 +323,10 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
'custom/Espo/Custom/Modules/TestModule',
'custom/Espo/Custom/Modules/TestModule/SubFolder',
'custom/Espo/Custom/Modules/TestModule/SubFolder/Tester.txt',
)
),
]
],
array( 'Set2', array(
['Set2', [
'custom',
'custom/Espo',
'custom/Espo/Custom',
@@ -336,15 +334,15 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
'custom/Espo/Custom/Resources/metadata',
'custom/Espo/Custom/Resources/metadata/entityDefs',
'custom/Espo/Custom/Resources/metadata/entityDefs/Account.json',
)
),
]
],
array( 'Set3', array(
['Set3', [
'custom',
'custom/test.file',
)
),
);
]
],
];
}
/**
@@ -353,7 +351,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
public function testRemoveWithEmptyDirs($name, $result)
{
$path = Util::fixPath($this->filesPath . '/Remove/' . $name);
$cachePath = Util::fixPath($this->cachePath . '/' . $name);
$cachePath = Util::fixPath(self::CACHE_PATH . '/' . $name);
$result = array_map('\Espo\Core\Utils\Util::fixPath', $result);
$fileList = array (
@@ -370,15 +368,15 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
}
}
public function existsPathSet()
static public function existsPathSet()
{
return array(
array( 'application/Espo/Core/Application.php', 'application/Espo/Core/Application.php', ),
array( 'application/Espo/Core/NotRealApplication.php', 'application/Espo/Core'),
array( 'application/Espo/Core/NotRealApplication.php', 'application/Espo/Core'),
array( 'application/NoEspo/Core/Application.php', 'application'),
array( 'notRealPath/Espo/Core/Application.php', '.'),
);
return [
['application/Espo/Core/Application.php', 'application/Espo/Core/Application.php',],
['application/Espo/Core/NotRealApplication.php', 'application/Espo/Core'],
['application/Espo/Core/NotRealApplication.php', 'application/Espo/Core'],
['application/NoEspo/Core/Application.php', 'application'],
['notRealPath/Espo/Core/Application.php', '.'],
];
}
/**
@@ -395,7 +393,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
public function testCopyTestCase1()
{
$path = Util::fixPath($this->filesPath . '/copy/testCase1');
$cachePath = Util::fixPath($this->cachePath . '/copy/testCase1');
$cachePath = Util::fixPath(self::CACHE_PATH . '/copy/testCase1');
$expectedResult = [
'custom/Espo/Custom/Modules/ExtensionTest/File.json',
@@ -416,7 +414,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
public function testCopyTestCase2()
{
$path = Util::fixPath($this->filesPath . '/copy/testCase2');
$cachePath = Util::fixPath($this->cachePath . '/copy/testCase2');
$cachePath = Util::fixPath(self::CACHE_PATH . '/copy/testCase2');
$expectedResult = [
'custom/Espo/Custom/test1.php',
@@ -438,7 +436,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
public function testCopyTestCase3()
{
$path = Util::fixPath($this->filesPath . '/copy/testCase3');
$cachePath = Util::fixPath($this->cachePath . '/copy/testCase3');
$cachePath = Util::fixPath(self::CACHE_PATH . '/copy/testCase3');
$expectedResult = [
'custom/Espo/Custom/test1.php',
@@ -469,7 +467,7 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
public function testCopyTestCase4()
{
$path = Util::fixPath($this->filesPath . '/copy/testCase4');
$cachePath = Util::fixPath($this->cachePath . '/copy/testCase4');
$cachePath = Util::fixPath(self::CACHE_PATH . '/copy/testCase4');
$expectedResult = [
'custom',
@@ -502,9 +500,9 @@ class ManagerTest extends \PHPUnit\Framework\TestCase
}
}
public function relativePathData()
static public function relativePathData()
{
$tmpPath = $this->cachePath;
$tmpPath = self::CACHE_PATH;
if (!file_exists($tmpPath)) {
mkdir($tmpPath, 0775, true);

View File

@@ -29,27 +29,26 @@
namespace tests\unit\Espo\Core\Utils\File;
use Espo\Core\Utils\File\Permission;
use PHPUnit\Framework\TestCase;
use tests\unit\ReflectionHelper;
class PermissionTest extends \PHPUnit\Framework\TestCase
class PermissionTest extends TestCase
{
protected $object;
protected $objects;
protected $reflection;
protected $fileList;
protected function setUp() : void
{
$this->objects['fileManager'] = $this->getMockBuilder('\Espo\Core\Utils\File\Manager')->disableOriginalConstructor()->getMock();
$this->object = new \Espo\Core\Utils\File\Permission($this->objects['fileManager']);
$this->object = new Permission($this->objects['fileManager']);
$this->reflection = new ReflectionHelper($this->object);
$this->fileList = array(
$this->fileList = [
'application/Espo/Controllers/Email.php',
'application/Espo/Controllers/EmailAccount.php',
'application/Espo/Controllers/EmailAddress.php',
@@ -64,7 +63,7 @@ class PermissionTest extends \PHPUnit\Framework\TestCase
'application/Espo/Resources/layouts/User/filters.json',
'application/Espo/Resources/metadata/app/acl.json',
'application/Espo/Resources/metadata/app/defaultDashboardLayout.json'
);
];
}
protected function tearDown() : void
@@ -102,7 +101,7 @@ class PermissionTest extends \PHPUnit\Framework\TestCase
$this->assertEquals( $result, $this->object->arrangePermissionList($this->fileList) );
}
public function requiredPermissionsData()
static public function requiredPermissionsData()
{
return [
['data/config.php', '0775', '0664'],

View File

@@ -31,8 +31,9 @@ namespace tests\unit\Espo\Core\Utils;
use Espo\Core\Utils\Module;
use Espo\Core\Utils\File\Manager as FileManager;
use PHPUnit\Framework\TestCase;
class ModuleTest extends \PHPUnit\Framework\TestCase
class ModuleTest extends TestCase
{
/** @var Module */
private $module;
@@ -49,61 +50,46 @@ class ModuleTest extends \PHPUnit\Framework\TestCase
public function testOrder1(): void
{
$this->fileManager
->expects(self::any())
->method('getDirList')
->withConsecutive(
['application/Espo/Modules'],
['custom/Espo/Modules'],
)
->willReturnOnConsecutiveCalls(
['M01', 'M02', 'M1', 'M2'],
['M3', 'M4', 'M51', 'M52'],
);
->willReturnMap([
[
'application/Espo/Modules',
['M01', 'M02', 'M1', 'M2'],
],
[
'custom/Espo/Modules',
['M3', 'M4', 'M51', 'M52'],
]
]);
$this->fileManager
->expects(self::any())
->method('exists')
->withConsecutive(
['application/Espo/Modules/M01/Resources/module.json'],
['application/Espo/Modules/M02/Resources/module.json'],
['application/Espo/Modules/M1/Resources/module.json'],
['application/Espo/Modules/M2/Resources/module.json'],
['custom/Espo/Modules/M3/Resources/module.json'],
['custom/Espo/Modules/M4/Resources/module.json'],
['custom/Espo/Modules/M51/Resources/module.json'],
['custom/Espo/Modules/M52/Resources/module.json'],
)
->willReturnOnConsecutiveCalls(
true,
true,
true,
true,
true,
true,
true,
true,
);
->willReturnMap([
['application/Espo/Modules/M01/Resources/module.json', true],
['application/Espo/Modules/M02/Resources/module.json', true],
['application/Espo/Modules/M1/Resources/module.json', true],
['application/Espo/Modules/M2/Resources/module.json', true],
['custom/Espo/Modules/M3/Resources/module.json', true],
['custom/Espo/Modules/M4/Resources/module.json', true],
['custom/Espo/Modules/M51/Resources/module.json', true],
['custom/Espo/Modules/M52/Resources/module.json', true],
]);
$this->fileManager
->expects(self::any())
->method('getContents')
->withConsecutive(
['application/Espo/Modules/M01/Resources/module.json'],
['application/Espo/Modules/M02/Resources/module.json'],
['application/Espo/Modules/M1/Resources/module.json'],
['application/Espo/Modules/M2/Resources/module.json'],
['custom/Espo/Modules/M3/Resources/module.json'],
['custom/Espo/Modules/M4/Resources/module.json'],
['custom/Espo/Modules/M51/Resources/module.json'],
['custom/Espo/Modules/M52/Resources/module.json'],
)
->willReturnOnConsecutiveCalls(
'{"order": 11}',
'{"order": 11}',
'{"order": 4}',
'{"order": 3}',
'{"order": 2}',
'{"order": 1}',
'{"order": 12}',
'{"order": 12}',
);
->willReturnMap([
['application/Espo/Modules/M01/Resources/module.json', '{"order": 11}'],
['application/Espo/Modules/M02/Resources/module.json', '{"order": 11}'],
['application/Espo/Modules/M1/Resources/module.json', '{"order": 4}'],
['application/Espo/Modules/M2/Resources/module.json', '{"order": 3}'],
['custom/Espo/Modules/M3/Resources/module.json', '{"order": 2}'],
['custom/Espo/Modules/M4/Resources/module.json', '{"order": 1}'],
['custom/Espo/Modules/M51/Resources/module.json', '{"order": 12}'],
['custom/Espo/Modules/M52/Resources/module.json', '{"order": 12}'],
]);
$this->assertEquals(
['M4', 'M3', 'M2', 'M1', 'M01', 'M02', 'M51', 'M52'],

View File

@@ -1179,7 +1179,7 @@ class UtilTest extends \PHPUnit\Framework\TestCase
);
}
public function getClassNames(): array
static public function getClassNames(): array
{
return [
'application/Espo/EntryPoints/Download.php' => ['application/Espo/EntryPoints/Download.php'],
@@ -1599,10 +1599,10 @@ class UtilTest extends \PHPUnit\Framework\TestCase
'newAttr2' => false,
);
$this->assertEquals($result, \Espo\Core\Utils\Util::arrayDiff($array1, $array2));
$this->assertEquals($result, Util::arrayDiff($array1, $array2));
}
public function htmlList()
static public function htmlList()
{
return [
['Test&lt;script&gt;alert(&quot;test&quot;)&lt;/script&gt;', 'Test<script>alert("test")</script>'],
@@ -1622,7 +1622,7 @@ class UtilTest extends \PHPUnit\Framework\TestCase
$this->assertEquals($expectedResult, Util::sanitizeHtml($html));
}
public function urlAddParamList()
static public function urlAddParamList()
{
return [
['https://test.link/?param1=1111', 'https://test.link', 'param1', '1111'],
@@ -1644,7 +1644,7 @@ class UtilTest extends \PHPUnit\Framework\TestCase
$this->assertEquals($expectedResult, Util::urlAddParam($url, $paramName, $paramValue));
}
public function urlRemoveParamList()
static public function urlRemoveParamList()
{
return [
['https://test.link', 'https://test.link', 'param1'],

View File

@@ -29,23 +29,26 @@
namespace tests\unit\Espo\ORM;
use Espo\ORM\{
TransactionManager,
QueryComposer\MysqlQueryComposer,
EntityFactory,
Metadata,
Locker\BaseLocker,
};
use Espo\ORM\EntityFactory;
use Espo\ORM\Locker\BaseLocker;
use Espo\ORM\Metadata;
use Espo\ORM\QueryComposer\MysqlQueryComposer;
use Espo\ORM\TransactionManager;
use PDO;
use PHPUnit\Framework\TestCase;
class BaseLockerTest extends \PHPUnit\Framework\TestCase
class BaseLockerTest extends TestCase
{
private $transactionManager;
private $locker;
private $pdo;
protected function setUp() : void
{
$this->pdo = $this->getMockBuilder(PDO::class)->disableOriginalConstructor()->getMock();
$this->pdo = $this->createMock(PDO::class);
$entityFactory = $this->getMockBuilder(EntityFactory::class)->disableOriginalConstructor()->getMock();
$entityFactory = $this->createMock(EntityFactory::class);
$metadata = $this->getMockBuilder(Metadata::class)->disableOriginalConstructor()->getMock();
@@ -63,13 +66,22 @@ class BaseLockerTest extends \PHPUnit\Framework\TestCase
->expects($this->exactly(2))
->method('start');
$invokedCount = $this->exactly(2);
$this->pdo
->expects($this->exactly(2))
->expects($invokedCount)
->method('exec')
->withConsecutive(
['LOCK TABLES `account` WRITE'],
['LOCK TABLES `contact` READ'],
);
->willReturnCallback(function ($sql) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('LOCK TABLES `account` WRITE', $sql);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('LOCK TABLES `contact` READ', $sql);
}
return 1;
});
$this->transactionManager
->expects($this->once())
@@ -91,13 +103,22 @@ class BaseLockerTest extends \PHPUnit\Framework\TestCase
->expects($this->exactly(2))
->method('start');
$invokedCount = $this->exactly(2);
$this->pdo
->expects($this->exactly(2))
->expects($invokedCount)
->method('exec')
->withConsecutive(
['LOCK TABLES `account` WRITE'],
['LOCK TABLES `contact` READ'],
);
->willReturnCallback(function ($sql) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('LOCK TABLES `account` WRITE', $sql);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('LOCK TABLES `contact` READ', $sql);
}
return 1;
});
$this->transactionManager
->expects($this->once())

View File

@@ -27,6 +27,8 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
/** @noinspection PhpVariableIsUsedOnlyInClosureInspection */
namespace tests\unit\Espo\ORM;
use Espo\ORM\CollectionFactory;
@@ -44,6 +46,8 @@ use Espo\ORM\QueryComposer\QueryComposerWrapper;
use Espo\ORM\Executor\SqlExecutor;
use Espo\ORM\SthCollection;
use PHPUnit\Framework\TestCase;
use RuntimeException;
use tests\unit\testData\DB\Comment;
use tests\unit\testData\DB\Note;
use tests\unit\testData\DB\Post;
@@ -54,7 +58,7 @@ use PDOStatement;
require_once 'tests/unit/testData/DB/Entities.php';
class MapperTest extends \PHPUnit\Framework\TestCase
class MapperTest extends TestCase
{
protected $db;
protected $pdo;
@@ -62,6 +66,15 @@ class MapperTest extends \PHPUnit\Framework\TestCase
protected $note;
protected $comment;
protected $entityFactory;
protected $team;
protected $account;
protected $contact;
protected $postData;
protected $tag;
protected $query;
protected $sqlExecutor;
protected $metadata;
private ?CollectionFactory $collectionFactory = null;
protected function setUp() : void
@@ -70,11 +83,11 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$this->pdo
->expects($this->any())
->method('quote')
->will($this->returnCallback(function() {
->willReturnCallback(function() {
$args = func_get_args();
return "'" . $args[0] . "'";
}));
});
$ormMetadata = include('tests/unit/testData/DB/ormMetadata.php');
@@ -92,28 +105,26 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$entityManager
->method('getMetadata')
->will($this->returnValue($this->metadata));
->willReturn($this->metadata);
$this->entityFactory = $this->createMock(EntityFactory::class);
$this->entityFactory
->expects($this->any())
->method('create')
->will($this->returnCallback(
->willReturnCallback(
function () use ($entityManager) {
$args = func_get_args();
$className = "tests\\unit\\testData\\DB\\" . $args[0];
$defs = $this->metadata->get($args[0]) ?? [];
return new $className($args[0], $defs, $entityManager);
}
));
);
$entityManager
->method('getEntityFactory')
->will($this->returnValue($this->entityFactory));
->willReturn($this->entityFactory);
$entityFactory = $this->entityFactory;
@@ -130,7 +141,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$this->entityFactory,
$this->collectionFactory,
$this->metadata,
$queryExecutor
$queryExecutor,
);
$this->post = $entityFactory->create('Post');
@@ -156,7 +167,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
if (!$noIteration) {
$values = [];
foreach ($data as $i => $item) {
foreach ($data as $item) {
$values[] = $item;
}
@@ -167,7 +178,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$sth->expects($this->any())
->method('fetchAll')
->will($this->returnValue($data));
->willReturn($data);
return $sth;
}
@@ -182,15 +193,14 @@ class MapperTest extends \PHPUnit\Framework\TestCase
if ($return === true) {
$return = $this->createSthMock([]);
} else
if (is_array($return)) {
} else if (is_array($return)) {
$return = $this->createSthMock($return, $noIteration);
}
$this->sqlExecutor->expects($expects)
->method('execute')
->with($sql)
->will($this->returnValue($return));
->method('execute')
->with($sql)
->willReturn($return);
}
protected function mockSqlCollection(string $entityType, string $sql, SthCollection $collection)
@@ -206,8 +216,6 @@ class MapperTest extends \PHPUnit\Framework\TestCase
{
$collection = $this->getMockBuilder(SthCollection::class)->disableOriginalConstructor()->getMock();
$itemList = $itemList ?? [];
$generator = (function () use ($itemList) {
foreach ($itemList as $item) {
yield $item;
@@ -217,8 +225,8 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$collection
->expects($this->any())
->method('getIterator')
->will(
$this->returnValue($generator)
->willReturn(
$generator
);
return $collection;
@@ -253,7 +261,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$post = $this->db->selectOne($select);
$this->assertEquals($post->id, '1');
$this->assertEquals('1', $post->id);
}
public function testSelect1(): void
@@ -310,7 +318,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$this->assertTrue($entity instanceof Post);
$this->assertTrue(isset($entity->id));
$this->assertEquals($entity->id, '2');
$this->assertEquals('2', $entity->id);
}
public function testSelectWithSpecifiedParams(): void
@@ -631,7 +639,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$count = $this->db->countRelated($this->post, 'tags');
$this->assertEquals($count, 1);
$this->assertEquals(1, $count);
}
public function testCount1(): void
@@ -667,9 +675,8 @@ class MapperTest extends \PHPUnit\Framework\TestCase
public function testInsert()
{
$query = "INSERT INTO `post` (`id`, `name`) VALUES ('1', 'test')";
$return = true;
$this->mockQuery($query, $return);
$this->mockQuery($query);
$this->post->reset();
$this->post->id = '1';
@@ -684,8 +691,8 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$query =
"INSERT INTO `post` (`id`, `name`, `deleted`) VALUES ('1', 'test', 0) " .
"ON DUPLICATE KEY UPDATE `name` = 'test', `deleted` = 0";
$return = true;
$this->mockQuery($query, $return);
$this->mockQuery($query);
$this->post->reset();
$this->post->id = '1';
@@ -698,8 +705,8 @@ class MapperTest extends \PHPUnit\Framework\TestCase
public function testMassInsert()
{
$query = "INSERT INTO `post` (`id`, `name`) VALUES ('1', 'test1'), ('2', 'test2')";
$return = true;
$this->mockQuery($query, $return);
$this->mockQuery($query);
$post1 = $this->entityFactory->create('Post');
$post2 = $this->entityFactory->create('Post');
@@ -721,8 +728,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
public function testUpdate1()
{
$query = "UPDATE `post` SET post.name = 'test' WHERE post.id = '1' AND post.deleted = 0";
$return = true;
$this->mockQuery($query, $return);
$this->mockQuery($query);
$this->post->reset();
$this->post->id = '1';
@@ -734,8 +740,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
public function testUpdate2()
{
$query = "UPDATE `post` SET post.name = 'test', post.deleted = 0 WHERE post.id = '1' AND post.deleted = 0";
$return = true;
$this->mockQuery($query, $return);
$this->mockQuery($query);
$this->post->reset();
$this->post->id = '1';
@@ -749,7 +754,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
{
$query = "UPDATE `job` SET job.array = '[\"2\",\"1\"]' WHERE job.id = '1' AND job.deleted = 0";
$this->mockQuery($query, true);
$this->mockQuery($query);
$job = $this->entityFactory->create('Job');
$job->id = '1';
@@ -763,7 +768,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
{
$query = "UPDATE `job` SET job.array = NULL WHERE job.id = '1' AND job.deleted = 0";
$this->mockQuery($query, true);
$this->mockQuery($query);
$job = $this->entityFactory->create('Job');
$job->id = '1';
@@ -806,7 +811,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"UPDATE `note` SET note.parent_id = NULL, note.parent_type = NULL " .
"WHERE note.id = 'noteId' AND note.parent_id = 'postId' AND note.parent_type = 'Post' AND note.deleted = 0";
$this->mockQuery($query, true);
$this->mockQuery($query);
$this->note->id = 'noteId';
$this->post->id = 'postId';
@@ -820,7 +825,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"UPDATE `note` SET note.parent_id = NULL, note.parent_type = NULL " .
"WHERE note.id = 'noteId' AND note.deleted = 0";
$this->mockQuery($query, true);
$this->mockQuery($query);
$this->note->id = 'noteId';
$this->db->unrelateAll($this->note, 'parent');
@@ -832,7 +837,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"UPDATE `comment` SET comment.post_id = NULL " .
"WHERE comment.id = 'commentId' AND comment.post_id = 'postId' AND comment.deleted = 0";
$this->mockQuery($query, true);
$this->mockQuery($query);
$this->post->id = 'postId';
@@ -866,7 +871,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$this->db->unrelateById($this->post, 'postData', 'dataId');
}
public function testRemovenParentToChildren()
public function testRemovedParentToChildren()
{
$query =
"UPDATE `note` SET note.parent_id = NULL, note.parent_type = NULL " .
@@ -895,8 +900,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
public function testRemoveManyMany()
{
$query = "UPDATE `post_tag` SET post_tag.deleted = 1 WHERE post_tag.post_id = '1' AND post_tag.tag_id = '100'";
$return = true;
$this->mockQuery($query, $return);
$this->mockQuery($query);
$this->post->id = '1';
@@ -906,8 +910,8 @@ class MapperTest extends \PHPUnit\Framework\TestCase
public function testRemoveAllManyMany()
{
$query = "UPDATE `post_tag` SET post_tag.deleted = 1 WHERE post_tag.post_id = '1'";
$return = true;
$this->mockQuery($query, $return);
$this->mockQuery($query);
$this->post->id = '1';
@@ -920,7 +924,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"UPDATE `entity_team` SET entity_team.deleted = 1 ".
"WHERE entity_team.entity_id = '1' AND entity_team.team_id = '100' AND entity_team.entity_type = 'Account'";
$this->mockQuery($query, true);
$this->mockQuery($query);
$this->account->id = '1';
@@ -963,13 +967,26 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$query2 =
"UPDATE `comment` SET comment.post_id = 'p' WHERE comment.id = 'c' AND comment.deleted = 0";
$this->sqlExecutor->expects($this->exactly(2))
$invokedCount = $this->exactly(2);
$this->sqlExecutor
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1], [$query2])
->willReturnOnConsecutiveCalls(
$this->createSthMock([['value' => 1]]),
$this->createSthMock([])
);
->willReturnCallback(function ($sql) use ($invokedCount, $query1, $query2) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([['value' => 1]]);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($query2, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->post, 'comments', $this->comment);
}
@@ -986,13 +1003,26 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$query2 =
"UPDATE `note` SET note.parent_id = 'p', note.parent_type = 'Post' WHERE note.id = 'n' AND note.deleted = 0";
$this->sqlExecutor->expects($this->exactly(2))
$invokedCount = $this->exactly(2);
$this->sqlExecutor
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1], [$query2])
->willReturnOnConsecutiveCalls(
$this->createSthMock([['value' => 1]]),
$this->createSthMock([])
);
->willReturnCallback(function ($sql) use ($invokedCount, $query1, $query2) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([['value' => 1]]);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($query2, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->post, 'notes', $this->note);
}
@@ -1005,10 +1035,21 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$query1 =
"UPDATE `comment` SET comment.post_id = 'p' WHERE comment.id = 'c' AND comment.deleted = 0";
$this->sqlExecutor->expects($this->exactly(1))
$invokedCount = $this->exactly(1);
$this->sqlExecutor
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1])
->willReturnOnConsecutiveCalls($this->createSthMock([]));
->willReturnCallback(function ($sql) use ($invokedCount, $query1) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->comment, 'post', $this->post);
}
@@ -1021,10 +1062,20 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$query1 =
"UPDATE `note` SET note.parent_id = 'p', note.parent_type = 'Post' WHERE note.id = 'n' AND note.deleted = 0";
$this->sqlExecutor->expects($this->exactly(1))
$invokedCount = $this->exactly(1);
$this->sqlExecutor
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1])
->willReturnOnConsecutiveCalls($this->createSthMock([]));
->willReturnCallback(function ($sql) use ($invokedCount, $query1) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->note, 'parent', $this->post);
}
@@ -1040,10 +1091,26 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$query2 =
"UPDATE `post_data` SET post_data.post_id = 'p' WHERE post_data.id = 'd' AND post_data.deleted = 0";
$this->sqlExecutor->expects($this->exactly(2))
$invokedCount = $this->exactly(2);
$this->sqlExecutor
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1], [$query2])
->willReturnOnConsecutiveCalls($this->createSthMock([]), $this->createSthMock([]));
->willReturnCallback(function ($sql) use ($invokedCount, $query1, $query2) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([]);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($query2, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->postData, 'post', $this->post);
}
@@ -1063,14 +1130,32 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$query3 =
"UPDATE `post_data` SET post_data.post_id = 'p' WHERE post_data.id = 'd' AND post_data.deleted = 0";
$this->sqlExecutor->expects($this->exactly(3))
$invokedCount = $this->exactly(3);
$this->sqlExecutor
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1], [$query2], [$query3])
->willReturnOnConsecutiveCalls(
$this->createSthMock([['value' => 1]]),
$this->createSthMock([]),
$this->createSthMock([])
);
->willReturnCallback(function ($sql) use ($invokedCount, $query1, $query2, $query3) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([['value' => 1]]);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($query2, $sql);
return $this->createSthMock([]);
}
if ($invokedCount->numberOfInvocations() === 3) {
$this->assertEquals($query3, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->post, 'postData', $this->postData);
}
@@ -1092,20 +1177,38 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"INSERT INTO `post_tag` (`post_id`, `tag_id`, `role`) VALUES ('postId', 'tagId', 'Test') " .
"ON DUPLICATE KEY UPDATE `deleted` = 0, `role` = 'Test'";
$ps = $this->createMock(\PDOStatement::class);
$ps = $this->createMock(PDOStatement::class);
$ps->expects($this->exactly(1))
->method('rowCount')
->willReturn(0);
$invokedCount = $this->exactly(3);
$this->sqlExecutor
->expects($this->exactly(3))
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1], [$query2], [$query3])
->willReturnOnConsecutiveCalls(
$this->createSthMock([['value' => 1]]),
$ps,
$this->createSthMock([])
);
->willReturnCallback(function ($sql) use ($invokedCount, $query1, $query2, $query3, $ps) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([['value' => 1]]);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($query2, $sql);
return $ps;
}
if ($invokedCount->numberOfInvocations() === 3) {
$this->assertEquals($query3, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->post, 'tags', $this->tag, ['role' => 'Test']);
}
@@ -1127,20 +1230,37 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"UPDATE `post_tag` SET post_tag.deleted = 0, post_tag.role = 'Test' " .
"WHERE post_tag.post_id = 'postId' AND post_tag.tag_id = 'tagId'";
$ps = $this->createMock(\PDOStatement::class);
$ps = $this->createMock(PDOStatement::class);
$ps->expects($this->exactly(1))
->method('rowCount')
->willReturn(1);
$invokedCount = $this->exactly(3);
$this->sqlExecutor
->expects($this->exactly(3))
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1], [$query2], [$query3])
->willReturnOnConsecutiveCalls(
$this->createSthMock([['value' => 1]]),
$ps,
$this->createSthMock([])
);
->willReturnCallback(function ($sql) use ($invokedCount, $query1, $query2, $query3, $ps) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([['value' => 1]]);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($query2, $sql);
return $ps;
}
if ($invokedCount->numberOfInvocations() === 3) {
$this->assertEquals($query3, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->post, 'tags', $this->tag, ['role' => 'Test']);
}
@@ -1162,20 +1282,37 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"INSERT INTO `entity_team` (`entity_id`, `team_id`, `entity_type`) VALUES ('accountId', 'teamId', 'Account') " .
"ON DUPLICATE KEY UPDATE `deleted` = 0";
$ps = $this->createMock(\PDOStatement::class);
$ps = $this->createMock(PDOStatement::class);
$ps->expects($this->exactly(1))
->method('rowCount')
->willReturn(0);
$invokedCount = $this->exactly(3);
$this->sqlExecutor
->expects($this->exactly(3))
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1], [$query2], [$query3])
->willReturnOnConsecutiveCalls(
$this->createSthMock([['value' => 1]]),
$ps,
$this->createSthMock([])
);
->willReturnCallback(function ($sql) use ($invokedCount, $query1, $query2, $query3, $ps) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([['value' => 1]]);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($query2, $sql);
return $ps;
}
if ($invokedCount->numberOfInvocations() === 3) {
$this->assertEquals($query3, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->account, 'teams', $this->team);
}
@@ -1197,20 +1334,37 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"UPDATE `entity_team` SET entity_team.deleted = 0 " .
"WHERE entity_team.entity_id = 'accountId' AND entity_team.team_id = 'teamId' AND entity_team.entity_type = 'Account'";
$ps = $this->createMock(\PDOStatement::class);
$ps = $this->createMock(PDOStatement::class);
$ps->expects($this->exactly(1))
->method('rowCount')
->willReturn(1);
$invokedCount = $this->exactly(3);
$this->sqlExecutor
->expects($this->exactly(3))
->expects($invokedCount)
->method('execute')
->withConsecutive([$query1], [$query2], [$query3])
->willReturnOnConsecutiveCalls(
$this->createSthMock([['value' => 1]]),
$ps,
$this->createSthMock([])
);
->willReturnCallback(function ($sql) use ($invokedCount, $query1, $query2, $query3, $ps) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($query1, $sql);
return $this->createSthMock([['value' => 1]]);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($query2, $sql);
return $ps;
}
if ($invokedCount->numberOfInvocations() === 3) {
$this->assertEquals($query3, $sql);
return $this->createSthMock([]);
}
throw new RuntimeException();
});
$this->db->relate($this->account, 'teams', $this->team);
}
@@ -1261,7 +1415,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
$value = $this->db->max(Select::fromRaw(['from' => 'Post']), 'id');
$this->assertEquals($value, 10);
$this->assertEquals(10, $value);
}
public function testMassRelate()
@@ -1271,8 +1425,7 @@ class MapperTest extends \PHPUnit\Framework\TestCase
"SELECT '1' AS `v0`, tag.id AS `id` FROM `tag` WHERE tag.name = 'test' AND tag.deleted = 0 ".
"ON DUPLICATE KEY UPDATE `deleted` = 0";
$return = true;
$this->mockQuery($query, $return);
$this->mockQuery($query);
$this->post->id = '1';

View File

@@ -29,44 +29,53 @@
namespace tests\unit\Espo\ORM;
use Espo\ORM\{
TransactionManager,
QueryComposer\MysqlQueryComposer,
EntityFactory,
Metadata,
Locker\MysqlLocker,
};
use Espo\ORM\EntityFactory;
use Espo\ORM\Locker\MysqlLocker;
use Espo\ORM\Metadata;
use Espo\ORM\QueryComposer\MysqlQueryComposer;
use Espo\ORM\TransactionManager;
use PDO;
use PHPUnit\Framework\TestCase;
class MysqlLockerTest extends \PHPUnit\Framework\TestCase
class MysqlLockerTest extends TestCase
{
private $locker;
private $pdo;
protected function setUp() : void
{
$this->pdo = $this->getMockBuilder(PDO::class)->disableOriginalConstructor()->getMock();
$entityFactory = $this->getMockBuilder(EntityFactory::class)->disableOriginalConstructor()->getMock();
$metadata = $this->getMockBuilder(Metadata::class)->disableOriginalConstructor()->getMock();
$this->transactionManager = $this->getMockBuilder(TransactionManager::class)
->disableOriginalConstructor()->getMock();
$this->pdo = $this->createMock(PDO::class);
$entityFactory = $this->createMock(EntityFactory::class);
$metadata = $this->createMock(Metadata::class);
$transactionManager = $this->createMock(TransactionManager::class);
$composer = new MysqlQueryComposer($this->pdo, $entityFactory, $metadata);
$this->locker = new MysqlLocker($this->pdo, $composer, $this->transactionManager);
$this->locker = new MysqlLocker($this->pdo, $composer, $transactionManager);
}
public function testLockCommit()
{
$invokedCount = $this->exactly(3);
$this->pdo
->expects($this->exactly(3))
->expects($invokedCount)
->method('exec')
->withConsecutive(
['LOCK TABLES `account` WRITE'],
['LOCK TABLES `contact` READ'],
['UNLOCK TABLES'],
);
->willReturnCallback(function ($sql) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('LOCK TABLES `account` WRITE', $sql);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('LOCK TABLES `contact` READ', $sql);
}
if ($invokedCount->numberOfInvocations() === 3) {
$this->assertEquals('UNLOCK TABLES', $sql);
}
return 1;
});
$this->locker->lockExclusive('Account');
$this->locker->lockShare('Contact');
@@ -80,14 +89,26 @@ class MysqlLockerTest extends \PHPUnit\Framework\TestCase
public function testLockRollback()
{
$invokedCount = $this->exactly(3);
$this->pdo
->expects($this->exactly(3))
->expects($invokedCount)
->method('exec')
->withConsecutive(
['LOCK TABLES `account` WRITE'],
['LOCK TABLES `contact` READ'],
['UNLOCK TABLES'],
);
->willReturnCallback(function ($sql) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('LOCK TABLES `account` WRITE', $sql);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('LOCK TABLES `contact` READ', $sql);
}
if ($invokedCount->numberOfInvocations() === 3) {
$this->assertEquals('UNLOCK TABLES', $sql);
}
return 1;
});
$this->locker->lockExclusive('Account');
$this->locker->lockShare('Contact');

View File

@@ -35,9 +35,15 @@ use Espo\ORM\PDO\PDOProvider;
use PDO;
use PDOStatement;
use PDOException;
use PHPUnit\Framework\TestCase;
use RuntimeException;
class SqlExecutorTest extends \PHPUnit\Framework\TestCase
class SqlExecutorTest extends TestCase
{
private $pdo;
private $sth;
private $executor;
protected function setUp() : void
{
$this->pdo = $this->createMock(PDO::class);
@@ -60,7 +66,7 @@ class SqlExecutorTest extends \PHPUnit\Framework\TestCase
$this->pdo
->expects($this->once())
->method('query')
->will($this->returnValue($this->sth))
->willReturn($this->sth)
->with($sql);
$sth = $this->executor->execute($sql);
@@ -123,9 +129,7 @@ class SqlExecutorTest extends \PHPUnit\Framework\TestCase
try {
$this->executor->execute($sql);
} catch (PDOException $e) {
}
} catch (PDOException) {}
}
public function testExecuteDeadlock2()
@@ -136,15 +140,22 @@ class SqlExecutorTest extends \PHPUnit\Framework\TestCase
$e->errorInfo = [40001, 1213];
$invokedCount = $this->exactly(2);
$this->pdo
->expects($this->exactly(2))
->expects($invokedCount)
->method('query')
->will(
$this->onConsecutiveCalls(
$this->throwException($e),
$this->returnValue($this->sth)
)
);
->willReturnCallback(function () use ($invokedCount, $e) {
if ($invokedCount->numberOfInvocations() === 1) {
throw $e;
}
if ($invokedCount->numberOfInvocations() === 2) {
return $this->sth;
}
throw new RuntimeException();
});
$sth = $this->executor->execute($sql, true);

View File

@@ -29,56 +29,50 @@
namespace tests\unit\Espo\ORM;
use Espo\ORM\{
TransactionManager,
QueryComposer\MysqlQueryComposer,
};
use Espo\ORM\QueryComposer\MysqlQueryComposer;
use Espo\ORM\TransactionManager;
use PDO;
use PHPUnit\Framework\TestCase;
use RuntimeException;
class TransactionManagerTest extends \PHPUnit\Framework\TestCase
class TransactionManagerTest extends TestCase
{
private $pdo;
private $manager;
protected function setUp() : void
{
$this->pdo = $this->getMockBuilder(PDO::class)->disableOriginalConstructor()->getMock();
$this->pdo = $this->createMock(PDO::class);
$composer = $this->createMock(MysqlQueryComposer::class);
$this->composer = $this->getMockBuilder(MysqlQueryComposer::class)->disableOriginalConstructor()->getMock();
$this->composer
$composer
->expects($this->any())
->method('composeCreateSavepoint')
->will(
$this->returnCallback(
function ($name) {
return 'SAVEPOINT ' . $name;
}
)
->willReturnCallback(
function ($name) {
return 'SAVEPOINT ' . $name;
}
);
$this->composer
$composer
->expects($this->any())
->method('composeReleaseSavepoint')
->will(
$this->returnCallback(
function ($name) {
return 'RELEASE SAVEPOINT ' . $name;
}
)
->willReturnCallback(
function ($name) {
return 'RELEASE SAVEPOINT ' . $name;
}
);
$this->composer
$composer
->expects($this->any())
->method('composeRollbackToSavepoint')
->will(
$this->returnCallback(
function ($name) {
return 'ROLLBACK TO SAVEPOINT ' . $name;
}
)
->willReturnCallback(
function ($name) {
return 'ROLLBACK TO SAVEPOINT ' . $name;
}
);
$this->manager = new TransactionManager($this->pdo, $this->composer);
$this->manager = new TransactionManager($this->pdo, $composer);
}
public function testStartOnce()
@@ -96,15 +90,30 @@ class TransactionManagerTest extends \PHPUnit\Framework\TestCase
->expects($this->exactly(1))
->method('beginTransaction');
$invokedCount = $this->exactly(4);
$this->pdo
->expects($this->exactly(4))
->expects($invokedCount)
->method('exec')
->withConsecutive(
['SAVEPOINT POINT_1'],
['SAVEPOINT POINT_2'],
['RELEASE SAVEPOINT POINT_2'],
['ROLLBACK TO SAVEPOINT POINT_1'],
);
->willReturnCallback(function ($sql) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('SAVEPOINT POINT_1', $sql);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('SAVEPOINT POINT_2', $sql);
}
if ($invokedCount->numberOfInvocations() === 3) {
$this->assertEquals('RELEASE SAVEPOINT POINT_2', $sql);
}
if ($invokedCount->numberOfInvocations() === 4) {
$this->assertEquals('ROLLBACK TO SAVEPOINT POINT_1', $sql);
}
return 1;
});
$this->pdo
->expects($this->exactly(1))
@@ -121,13 +130,22 @@ class TransactionManagerTest extends \PHPUnit\Framework\TestCase
public function testNestedRollback()
{
$invokedCount = $this->exactly(2);
$this->pdo
->expects($this->exactly(2))
->expects($invokedCount)
->method('exec')
->withConsecutive(
['SAVEPOINT POINT_1'],
['ROLLBACK TO SAVEPOINT POINT_1'],
);
->willReturnCallback(function ($sql) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('SAVEPOINT POINT_1', $sql);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('ROLLBACK TO SAVEPOINT POINT_1', $sql);
}
return 1;
});
$this->pdo
->expects($this->once())
@@ -207,13 +225,22 @@ class TransactionManagerTest extends \PHPUnit\Framework\TestCase
->expects($this->once())
->method('beginTransaction');
$invokedCount = $this->exactly(2);
$this->pdo
->expects($this->exactly(2))
->expects($invokedCount)
->method('exec')
->withConsecutive(
['SAVEPOINT POINT_1'],
['RELEASE SAVEPOINT POINT_1'],
);
->willReturnCallback(function ($sql) use ($invokedCount) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals('SAVEPOINT POINT_1', $sql);
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals('RELEASE SAVEPOINT POINT_1', $sql);
}
return 1;
});
$this->pdo
->expects($this->once())

View File

@@ -42,11 +42,16 @@ class FieldManagerTest extends TestCase
private ?FieldManager $fieldManager = null;
private ?NameUtil $nameUtil = null;
private $metadataHelper;
private $language;
protected $defaultLanguage;
protected $metadata;
protected function setUp() : void
{
$this->metadata = $this->createMock(Metadata::class);
$this->language = $this->createMock(Language::class);
$this->baseLanguage = $this->createMock(Language::class);
$baseLanguage = $this->createMock(Language::class);
$this->defaultLanguage = $this->createMock(Language::class);
$this->metadataHelper = $this->createMock(Metadata\Helper::class);
$this->nameUtil = $this->createMock(NameUtil::class);
@@ -59,7 +64,7 @@ class FieldManagerTest extends TestCase
$this->createMock(InjectableFactory::class),
$this->metadata,
$this->language,
$this->baseLanguage,
$baseLanguage,
$this->metadataHelper,
$this->nameUtil
);
@@ -113,22 +118,22 @@ class FieldManagerTest extends TestCase
$this->language
->expects($this->once())
->method('save')
->will($this->returnValue(true));
->willReturn(true);
$this->metadata
->expects($this->any())
->method('get')
->will($this->returnValueMap($map));
->willReturnMap($map);
$this->metadata
->expects($this->exactly(2))
->method('getObjects')
->will($this->returnValue($existingData));
->willReturn($existingData);
$this->metadataHelper
->expects($this->once())
->method('getFieldDefsByType')
->will($this->returnValue(json_decode('{
->willReturn(json_decode('{
"params":[
{
"name":"required",
@@ -165,12 +170,12 @@ class FieldManagerTest extends TestCase
"personalData": true,
"textFilter": true,
"fullTextSearch": true
}', true)));
}', true));
$this->metadata
->expects($this->exactly(2))
->method('getCustom')
->will($this->returnValue((object) []));
->willReturn((object) []);
$this->fieldManager->update('Account', 'name', $data);
}
@@ -345,7 +350,7 @@ class FieldManagerTest extends TestCase
$this->metadata
->expects($this->exactly(2))
->method('getCustom')
->will($this->returnValue((object) []));
->willReturn((object) []);
$this->fieldManager->update('CustomEntity', 'varName', $data);
}

View File

@@ -33,8 +33,10 @@ use Espo\Core\Field\DateTime;
use Espo\Tools\WorkingTime\Calendar;
use Espo\Tools\WorkingTime\CalendarUtility;
use Espo\Tools\WorkingTime\Extractor;
use PHPUnit\Framework\TestCase;
use RuntimeException;
class CalendarUtilityTest extends \PHPUnit\Framework\TestCase
class CalendarUtilityTest extends TestCase
{
protected Calendar $calendar;
protected Extractor $extractor;
@@ -149,34 +151,41 @@ class CalendarUtilityTest extends \PHPUnit\Framework\TestCase
public function testFindClosestWorkingTime1(): void
{
$time = DateTime::fromString('2023-01-01 00:00:00');
$point = DateTime::fromString('2023-01-01 00:00:00');
$invokedCount = $this->exactly(2);
$this->extractor
->expects($this->exactly(2))
->expects($invokedCount)
->method('extract')
->withConsecutive(
[
$this->calendar,
$time,
$time->modify('+10 days')
],
[
$this->calendar,
$time->modify('+10 days'),
$time->modify('+20 days'),
]
)
->willReturnOnConsecutiveCalls(
[],
[
[
DateTime::fromString('2023-01-11 01:00:00'),
DateTime::fromString('2023-01-11 02:00:00')
],
]
);
->willReturnCallback(function ($calendar, $a, $b) use ($invokedCount, $point) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($this->calendar, $calendar);
$this->assertEquals($point, $a);
$this->assertEquals($point->modify('+10 days'), $b);
$found = $this->calendarUtility->findClosestWorkingTime($time);
return [];
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($this->calendar, $calendar);
$this->assertEquals($point->modify('+10 days'), $a);
$this->assertEquals($point->modify('+20 days'), $b);
return [
[
DateTime::fromString('2023-01-11 01:00:00'),
DateTime::fromString('2023-01-11 02:00:00')
],
];
}
throw new RuntimeException();
});
$found = $this->calendarUtility->findClosestWorkingTime($point);
$this->assertEquals(DateTime::fromString('2023-01-11 01:00:00'), $found);
}
@@ -201,30 +210,35 @@ class CalendarUtilityTest extends \PHPUnit\Framework\TestCase
$point = $time->withTime(0, 0, 0)->modify('+1 day');
$invokedCount = $this->exactly(2);
$this->extractor
->expects($this->exactly(2))
->expects($invokedCount)
->method('extractAllDay')
->withConsecutive(
[
$this->calendar,
$point,
$point->modify('+30 days')
],
[
$this->calendar,
$point->modify('+30 days'),
$point->modify('+60 days'),
]
)
->willReturnOnConsecutiveCalls(
[],
[
[
DateTime::fromString('2023-04-01 00:00:00'),
DateTime::fromString('2023-04-01 00:00:00')
],
]
);
->willReturnCallback(function ($calendar, $a, $b) use ($invokedCount, $point) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($this->calendar, $calendar);
$this->assertEquals($point, $a);
$this->assertEquals($point->modify('+30 days'), $b);
return [];
}
if ($invokedCount->numberOfInvocations() === 2) {
$this->assertEquals($this->calendar, $calendar);
$this->assertEquals($point->modify('+30 days'), $a);
$this->assertEquals($point->modify('+60 days'), $b);
return [
[
DateTime::fromString('2023-04-01 00:00:00'),
DateTime::fromString('2023-04-01 00:00:00')
],
];
}
throw new RuntimeException();
});
$found = $this->calendarUtility->addWorkingDays($time, 1);
@@ -237,28 +251,31 @@ class CalendarUtilityTest extends \PHPUnit\Framework\TestCase
$point = $time->withTime(0, 0, 0)->modify('+1 day');
$invokedCount = $this->exactly(1);
$this->extractor
->expects($this->exactly(1))
->expects($invokedCount)
->method('extractAllDay')
->withConsecutive(
[
$this->calendar,
$point,
$point->modify('+30 days')
],
)
->willReturnOnConsecutiveCalls(
[
[
DateTime::fromString('2023-01-02 00:00:00'),
DateTime::fromString('2023-01-03 00:00:00')
],
[
DateTime::fromString('2023-01-03 00:00:00'),
DateTime::fromString('2023-01-04 00:00:00')
],
]
);
->willReturnCallback(function ($calendar, $a, $b) use ($invokedCount, $point) {
if ($invokedCount->numberOfInvocations() === 1) {
$this->assertEquals($this->calendar, $calendar);
$this->assertEquals($point, $a);
$this->assertEquals($point->modify('+30 days'), $b);
return [
[
DateTime::fromString('2023-01-02 00:00:00'),
DateTime::fromString('2023-01-03 00:00:00')
],
[
DateTime::fromString('2023-01-03 00:00:00'),
DateTime::fromString('2023-01-04 00:00:00')
],
];
}
throw new RuntimeException();
});
$found = $this->calendarUtility->addWorkingDays($time, 2);