Skip to content

Commit

Permalink
Improved code to follow better coding standards. Part 2.
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexSkrypnyk committed Dec 7, 2024
1 parent 2a7f68b commit 0bba2ba
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 70 deletions.
39 changes: 11 additions & 28 deletions tests/phpunit/Functional/TokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ class TokenTest extends AbstractFunctionalTestCase {
/**
* @dataProvider dataProviderTokenProcess
*/
public function testTokenProcess(string $string, string $name, string $replacement, string $expectedString): void {
$mock = $this->prepareMock(TokenTrait::class, [
'getToken' . ucfirst($name) => static function (?string $prop) use ($replacement): string {
return empty($prop) ? $replacement : $replacement . ' with property ' . $prop;
},
]);
public function testTokenProcess(string $string, string $expected): void {
$class = new class() {
use TokenTrait;

$actual = $this->callProtectedMethod($mock, 'tokenProcess', [$string]);
$this->assertEquals($expectedString, $actual);
public function getTokenSomeToken(?string $prop = NULL): string {
return empty($prop) ? 'somevalue' : 'somevalue with property ' . $prop;
}

};

$actual = $this->callProtectedMethod($class, 'tokenProcess', [$string]);
$this->assertEquals($expected, $actual);
}

/**
Expand All @@ -38,63 +41,43 @@ public static function dataProviderTokenProcess(): array {
[
'',
'',
'',
'',
],
[
'',
'sometoken',
'somevalue',
'',
],
[
'string without a token',
'sometoken',
'somevalue',
'string without a token',
],
[
'string with sometoken without delimiters',
'sometoken',
'somevalue',
'string with sometoken without delimiters',
],
[
'string with [sometoken broken delimiters',
'sometoken',
'somevalue',
'string with [sometoken broken delimiters',
],
[
'string with sometoken] broken delimiters',
'sometoken',
'somevalue',
'string with sometoken] broken delimiters',
],
// Proper token.
[
'[sometoken]',
'sometoken',
'somevalue',
'somevalue',
],
[
'string with [sometoken] present',
'sometoken',
'somevalue',
'string with somevalue present',
],
// Token with properties.
[
'string with [sometoken:prop] present',
'sometoken',
'somevalue',
'string with somevalue with property prop present',
],
[
'string with [sometoken:prop:otherprop] present',
'sometoken',
'somevalue',
'string with somevalue with property prop:otherprop present',
],
];
Expand Down
2 changes: 0 additions & 2 deletions tests/phpunit/Traits/CommandTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,6 @@ protected function runCliCommand(string $command): array {
* Expected assert.
* @param array $array
* The array want to assert.
*
* @phpstan-ignore-next-line
*/
protected function assertArraySimilar(array $expected, array $array): void {
$this->assertEquals([], array_diff($array, $expected));
Expand Down
67 changes: 29 additions & 38 deletions tests/phpunit/Traits/MockTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace DrevOps\GitArtifact\Tests\Traits;

use PHPUnit\Framework\MockObject\MockObject;

/**
* Trait MockTrait.
*
Expand All @@ -16,61 +18,50 @@ trait MockTrait {
*
* @param class-string $class
* Class or trait name to generate the mock.
* @param array<string, \Closure> $methodsMap
* @param array<string, scalar|\Closure> $methods
* Optional array of methods and values, keyed by method name. Array
* elements can be return values, callbacks created with
* $this->returnCallback(), or closures.
* @param array<mixed> $args
* Optional array of constructor arguments. If omitted, a constructor
* will not be called.
* $this->willReturnCallback(), or closures.
* @param bool|array<mixed> $args
* Optional array of constructor arguments or FALSE to disable the original
* constructor. If omitted, an original constructor will be called.
*
* @return object
* @return \PHPUnit\Framework\MockObject\MockObject
* Mocked class.
*
* @throws \ReflectionException
*
* @SuppressWarnings(CyclomaticComplexity)
*/
protected function prepareMock(string $class, array $methodsMap = [], array $args = []) {
$methods = array_keys($methodsMap);
protected function prepareMock(string $class, array $methods = [], array|bool $args = []): MockObject {
$methods = array_filter($methods, fn($value, $key): bool => is_string($key), ARRAY_FILTER_USE_BOTH);

$reflectionClass = new \ReflectionClass($class);
if (!class_exists($class)) {
throw new \InvalidArgumentException(sprintf('Class %s does not exist', $class));
}

if ($reflectionClass->isAbstract()) {
$mock = $this->getMockForAbstractClass($class, $args, '', !empty($args), TRUE, TRUE, $methods);
$builder = $this->getMockBuilder($class);

if (is_array($args) && !empty($args)) {
$builder->enableOriginalConstructor()->setConstructorArgs($args);
}
elseif ($reflectionClass->isTrait()) {
$mock = $this->getMockForTrait($class, [], '', TRUE, TRUE, TRUE, array_keys($methodsMap));
}
else {
$mockBuilder = $this->getMockBuilder($class);
if (!empty($args)) {
$mockBuilder = $mockBuilder->enableOriginalConstructor()
->setConstructorArgs($args);
}
else {
$mockBuilder = $mockBuilder->disableOriginalConstructor();
}
/* @todo setMethods method is not found on MockBuilder */
/* @phpstan-ignore-next-line */
$mock = $mockBuilder->setMethods($methods)
->getMock();
elseif ($args === FALSE) {
$builder->disableOriginalConstructor();
}

foreach ($methodsMap as $method => $value) {
// Handle callback values differently.
$method_names = array_filter(array_keys($methods), fn($method): bool => is_string($method) && !empty($method));
$mock = $builder->onlyMethods($method_names)->getMock();

foreach ($methods as $method => $value) {
// Handle callback value differently based on its type.
if (is_object($value) && str_contains($value::class, 'Callback')) {
$mock->expects($this->any())
->method($method)
->will($value);
$mock->expects($this->any())->method($method)->willReturnCallback($value);
}
elseif (is_object($value) && str_contains($value::class, 'Closure')) {
$mock->expects($this->any())
->method($method)
->will($this->returnCallback($value));
$mock->expects($this->any())->method($method)->willReturnCallback($value);
}
else {
$mock->expects($this->any())
->method($method)
->willReturn($value);
$mock->expects($this->any())->method($method)->willReturn($value);
}
}

Expand Down
6 changes: 4 additions & 2 deletions tests/phpunit/Unit/TokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ class TokenTest extends AbstractUnitTestCase {
* @dataProvider dataProviderTokenExists
*/
public function testTokenExists(string $string, bool $expected): void {
$mock = $this->prepareMock(TokenTrait::class);
$class = new class() {
use TokenTrait;
};

$actual = $this->callProtectedMethod($mock, 'tokenExists', [$string]);
$actual = $this->callProtectedMethod($class, 'tokenExists', [$string]);
$this->assertEquals($expected, $actual);
}

Expand Down

0 comments on commit 0bba2ba

Please sign in to comment.