-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(testing): Add ability to test RunInTransaction/SafeUniqueSave ac…
…tions using assert/expectation classes - Using contract allows switching implementation - Assert triggers closures in expected "way"
- Loading branch information
Showing
11 changed files
with
264 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace LaraStrict\Database\Contracts; | ||
|
||
use Closure; | ||
|
||
interface RunInTransactionActionContract | ||
{ | ||
/** | ||
* @template T | ||
* | ||
* @param Closure():T $callback | ||
* | ||
* @return T | ||
*/ | ||
public function execute(Closure $callback, int $attempts = 1): mixed; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace LaraStrict\Database\Contracts; | ||
|
||
use Closure; | ||
use Illuminate\Database\Eloquent\Model; | ||
|
||
interface SafeUniqueSaveActionContract | ||
{ | ||
/** | ||
* Ensures that model will be reset if duplication error has occurred. | ||
* | ||
* @template T of Model | ||
* @template R | ||
* | ||
* @param T $model | ||
* @param Closure(T, int): R $setupClosure | ||
* | ||
* @return R Returns value from the closure (the latest value that was successfully stored) | ||
*/ | ||
public function execute(Model $model, Closure $setupClosure, int $maxTries = 20, int $tries = 1): mixed; | ||
} |
46 changes: 46 additions & 0 deletions
46
src/Testing/Database/Contracts/RunInTransactionActionContractAssert.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace LaraStrict\Testing\Database\Contracts; | ||
|
||
use Closure; | ||
use LaraStrict\Database\Contracts\RunInTransactionActionContract; | ||
use LaraStrict\Testing\AbstractExpectationCallMap; | ||
use PHPUnit\Framework\Assert; | ||
|
||
/** | ||
* @extends AbstractExpectationCallMap<RunInTransactionActionContractExpectation> | ||
*/ | ||
class RunInTransactionActionContractAssert extends AbstractExpectationCallMap implements RunInTransactionActionContract | ||
{ | ||
public function __construct(array $expectationMap = [ | ||
new RunInTransactionActionContractExpectation(false), | ||
], int $callStep = 0) | ||
{ | ||
parent::__construct($expectationMap, $callStep); | ||
} | ||
|
||
/** | ||
* @template T | ||
* | ||
* @param Closure():T $callback | ||
* | ||
* @return T | ||
*/ | ||
public function execute(Closure $callback, int $attempts = 1): mixed | ||
{ | ||
$expectation = $this->getExpectation(); | ||
$message = $this->getDebugMessage(); | ||
|
||
Assert::assertEquals($expectation->attempts, $attempts, $message); | ||
|
||
$result = $callback(); | ||
|
||
if ($expectation->fail) { | ||
return $this->execute($callback, $attempts + 1); | ||
} | ||
|
||
return $result; | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/Testing/Database/Contracts/RunInTransactionActionContractExpectation.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace LaraStrict\Testing\Database\Contracts; | ||
|
||
final class RunInTransactionActionContractExpectation | ||
{ | ||
public function __construct( | ||
public readonly bool $fail, | ||
public readonly int $attempts = 1, | ||
) { | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
src/Testing/Database/Contracts/SafeUniqueSaveActionContractAssert.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace LaraStrict\Testing\Database\Contracts; | ||
|
||
use Closure; | ||
use Illuminate\Database\Eloquent\Model; | ||
use LaraStrict\Database\Contracts\SafeUniqueSaveActionContract; | ||
use LaraStrict\Testing\AbstractExpectationCallMap; | ||
use PHPUnit\Framework\Assert; | ||
|
||
/** | ||
* @extends AbstractExpectationCallMap<SafeUniqueSaveActionContractExpectation> | ||
*/ | ||
class SafeUniqueSaveActionContractAssert extends AbstractExpectationCallMap implements SafeUniqueSaveActionContract | ||
{ | ||
/** | ||
* Ensures that model will be reset if duplication error has occurred. | ||
* | ||
* @template T of Model | ||
* @template R | ||
* | ||
* @param T $model | ||
* @param Closure(T, int): R $setupClosure | ||
* | ||
* @return R Returns value from the closure (the latest value that was successfully stored) | ||
*/ | ||
public function execute(Model $model, Closure $setupClosure, int $maxTries = 20, int $tries = 1): mixed | ||
{ | ||
$expectation = $this->getExpectation(); | ||
$message = $this->getDebugMessage(); | ||
|
||
Assert::assertEquals($expectation->model, $model, $message); | ||
Assert::assertEquals($expectation->maxTries, $maxTries, $message); | ||
Assert::assertEquals($expectation->tries, $tries, $message); | ||
|
||
$result = $setupClosure($model, $tries); | ||
|
||
if ($expectation->fail) { | ||
return $this->execute($model, $setupClosure, $maxTries, $tries + 1); | ||
} | ||
|
||
return $result; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/Testing/Database/Contracts/SafeUniqueSaveActionContractExpectation.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace LaraStrict\Testing\Database\Contracts; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
|
||
final class SafeUniqueSaveActionContractExpectation | ||
{ | ||
public function __construct( | ||
public readonly Model $model, | ||
public readonly bool $fail = false, | ||
public readonly int $maxTries = 20, | ||
public readonly int $tries = 1, | ||
) { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
tests/Unit/Testing/Database/Contracts/RunInTransactionActionContractAssertTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tests\LaraStrict\Unit\Testing\Database\Contracts; | ||
|
||
use LaraStrict\Testing\Database\Contracts\RunInTransactionActionContractAssert; | ||
use LaraStrict\Testing\Database\Contracts\RunInTransactionActionContractExpectation; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
class RunInTransactionActionContractAssertTest extends TestCase | ||
{ | ||
public function testExecuteWithFirstFailed(): void | ||
{ | ||
$assert = new RunInTransactionActionContractAssert([ | ||
new RunInTransactionActionContractExpectation(true), | ||
new RunInTransactionActionContractExpectation(false, 2), | ||
]); | ||
|
||
$count = 0; | ||
$assert->execute(static function () use (&$count) { | ||
++$count; | ||
}); | ||
|
||
$this->assertEquals(2, $count); | ||
} | ||
|
||
public function testExecuteDefaultRunClosureOnce(): void | ||
{ | ||
$assert = new RunInTransactionActionContractAssert(); | ||
|
||
$count = 0; | ||
$assert->execute(static function () use (&$count) { | ||
++$count; | ||
}); | ||
|
||
$this->assertEquals(1, $count); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
tests/Unit/Testing/Database/Contracts/SafeUniqueSaveActionContractAssertTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tests\LaraStrict\Unit\Testing\Database\Contracts; | ||
|
||
use LaraStrict\Testing\Database\Contracts\SafeUniqueSaveActionContractAssert; | ||
use LaraStrict\Testing\Database\Contracts\SafeUniqueSaveActionContractExpectation; | ||
use PHPUnit\Framework\TestCase; | ||
use Tests\LaraStrict\Feature\Database\Models\Test; | ||
|
||
class SafeUniqueSaveActionContractAssertTest extends TestCase | ||
{ | ||
public function testExecuteOneTry(): void | ||
{ | ||
$model = new Test(); | ||
$expectations = [new SafeUniqueSaveActionContractExpectation($model)]; | ||
$expectedResult = 'test1'; | ||
|
||
$this->assertExecute($expectations, $model, $expectedResult); | ||
} | ||
|
||
public function testExecuteTwoTries(): void | ||
{ | ||
$model = new Test(); | ||
$expectations = [ | ||
new SafeUniqueSaveActionContractExpectation($model, fail: true), | ||
new SafeUniqueSaveActionContractExpectation($model, tries: 2), | ||
]; | ||
$expectedResult = 'test2'; | ||
|
||
$this->assertExecute($expectations, $model, $expectedResult); | ||
} | ||
|
||
protected function assertExecute(array $expectations, Test $model, string $expectedResult): void | ||
{ | ||
$assert = new SafeUniqueSaveActionContractAssert($expectations); | ||
|
||
$calls = 0; | ||
$result = $assert->execute($model, function (Test $model, int $tries) use (&$calls) { | ||
++$calls; | ||
$this->assertEquals($calls, $tries); | ||
return 'test' . $calls; | ||
}); | ||
|
||
$this->assertEquals($expectedResult, $result); | ||
} | ||
} |