diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index bcb672a3c..8928c78e1 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -4,15 +4,11 @@ namespace MongoDB\Laravel\Eloquent; -use Brick\Math\BigDecimal; -use Brick\Math\Exception\MathException as BrickMathException; -use Brick\Math\RoundingMode; use Carbon\CarbonInterface; use DateTimeInterface; use Illuminate\Contracts\Queue\QueueableCollection; use Illuminate\Contracts\Queue\QueueableEntity; use Illuminate\Contracts\Support\Arrayable; -use Illuminate\Database\Eloquent\Casts\Json; use Illuminate\Database\Eloquent\Model as BaseModel; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Arr; @@ -22,10 +18,11 @@ use MongoDB\BSON\Binary; use MongoDB\BSON\Decimal128; use MongoDB\BSON\ObjectID; +use MongoDB\BSON\Type; use MongoDB\BSON\UTCDateTime; use MongoDB\Laravel\Query\Builder as QueryBuilder; +use Stringable; -use function abs; use function array_key_exists; use function array_keys; use function array_merge; @@ -41,7 +38,6 @@ use function is_string; use function ltrim; use function method_exists; -use function sprintf; use function str_contains; use function str_starts_with; use function strcmp; @@ -139,15 +135,9 @@ public function fromDateTime($value) /** @inheritdoc */ protected function asDateTime($value) { - // Convert UTCDateTime instances. + // Convert UTCDateTime instances to Carbon. if ($value instanceof UTCDateTime) { - $date = $value->toDateTime(); - - $seconds = $date->format('U'); - $milliseconds = abs((int) $date->format('v')); - $timestampMs = sprintf('%d%03d', $seconds, $milliseconds); - - return Date::createFromTimestampMs($timestampMs); + return Date::instance($value->toDateTime()); } return parent::asDateTime($value); @@ -250,9 +240,16 @@ public function setAttribute($key, $value) { $key = (string) $key; - // Add casts - if ($this->hasCast($key)) { - $value = $this->castAttribute($key, $value); + $casts = $this->getCasts(); + if (array_key_exists($key, $casts)) { + $castType = $this->getCastType($key); + $castOptions = Str::after($casts[$key], ':'); + + // Can add more native mongo type casts here. + $value = match ($castType) { + 'decimal' => $this->fromDecimal($value, $castOptions), + default => $value, + }; } // Convert _id to ObjectID. @@ -281,26 +278,38 @@ public function setAttribute($key, $value) return parent::setAttribute($key, $value); } - /** @inheritdoc */ + /** + * @param mixed $value + * + * @inheritdoc + */ protected function asDecimal($value, $decimals) { - try { - $value = (string) BigDecimal::of((string) $value)->toScale((int) $decimals, RoundingMode::HALF_UP); - - return new Decimal128($value); - } catch (BrickMathException $e) { - throw new MathException('Unable to cast value to a decimal.', previous: $e); + // Convert BSON to string. + if ($this->isBSON($value)) { + if ($value instanceof Binary) { + $value = $value->getData(); + } elseif ($value instanceof Stringable) { + $value = (string) $value; + } else { + throw new MathException('BSON type ' . $value::class . ' cannot be converted to string'); + } } + + return parent::asDecimal($value, $decimals); } - /** @inheritdoc */ - public function fromJson($value, $asObject = false) + /** + * Change to mongo native for decimal cast. + * + * @param mixed $value + * @param int $decimals + * + * @return Decimal128 + */ + protected function fromDecimal($value, $decimals) { - if (! is_string($value)) { - $value = Json::encode($value); - } - - return Json::decode($value, ! $asObject); + return new Decimal128($this->asDecimal($value, $decimals)); } /** @inheritdoc */ @@ -707,4 +716,16 @@ protected function addCastAttributesToArray(array $attributes, array $mutatedAtt return $attributes; } + + /** + * Is a value a BSON type? + * + * @param mixed $value + * + * @return bool + */ + protected function isBSON(mixed $value): bool + { + return $value instanceof Type; + } } diff --git a/tests/Casts/BooleanTest.php b/tests/Casts/BooleanTest.php index 8be2a4def..a4812ddec 100644 --- a/tests/Casts/BooleanTest.php +++ b/tests/Casts/BooleanTest.php @@ -50,5 +50,42 @@ public function testBoolAsString(): void self::assertIsBool($model->booleanValue); self::assertSame(false, $model->booleanValue); + + $model->update(['booleanValue' => 'false']); + + self::assertIsBool($model->booleanValue); + self::assertSame(true, $model->booleanValue); + + $model->update(['booleanValue' => '0.0']); + + self::assertIsBool($model->booleanValue); + self::assertSame(true, $model->booleanValue); + + $model->update(['booleanValue' => 'true']); + + self::assertIsBool($model->booleanValue); + self::assertSame(true, $model->booleanValue); + } + + public function testBoolAsNumber(): void + { + $model = Casting::query()->create(['booleanValue' => 1]); + + self::assertIsBool($model->booleanValue); + self::assertSame(true, $model->booleanValue); + + $model->update(['booleanValue' => 0]); + + self::assertIsBool($model->booleanValue); + self::assertSame(false, $model->booleanValue); + + $model->update(['booleanValue' => 1.79]); + + self::assertIsBool($model->booleanValue); + self::assertSame(true, $model->booleanValue); + + $model->update(['booleanValue' => 0.0]); + self::assertIsBool($model->booleanValue); + self::assertSame(false, $model->booleanValue); } } diff --git a/tests/Casts/CollectionTest.php b/tests/Casts/CollectionTest.php index 67498c092..4c2400ecb 100644 --- a/tests/Casts/CollectionTest.php +++ b/tests/Casts/CollectionTest.php @@ -24,11 +24,19 @@ public function testCollection(): void $model = Casting::query()->create(['collectionValue' => ['g' => 'G-Eazy']]); self::assertInstanceOf(Collection::class, $model->collectionValue); + self::assertIsString($model->getRawOriginal('collectionValue')); self::assertEquals(collect(['g' => 'G-Eazy']), $model->collectionValue); $model->update(['collectionValue' => ['Dont let me go' => 'Even the longest of nights turn days']]); self::assertInstanceOf(Collection::class, $model->collectionValue); + self::assertIsString($model->getRawOriginal('collectionValue')); self::assertEquals(collect(['Dont let me go' => 'Even the longest of nights turn days']), $model->collectionValue); + + $model->update(['collectionValue' => [['Dont let me go' => 'Even the longest of nights turn days']]]); + + self::assertInstanceOf(Collection::class, $model->collectionValue); + self::assertIsString($model->getRawOriginal('collectionValue')); + self::assertEquals(collect([['Dont let me go' => 'Even the longest of nights turn days']]), $model->collectionValue); } } diff --git a/tests/Casts/DateTest.php b/tests/Casts/DateTest.php index bd4b76424..20ce5dd9a 100644 --- a/tests/Casts/DateTest.php +++ b/tests/Casts/DateTest.php @@ -7,6 +7,7 @@ use Carbon\CarbonImmutable; use DateTime; use Illuminate\Support\Carbon; +use MongoDB\BSON\UTCDateTime; use MongoDB\Laravel\Tests\Models\Casting; use MongoDB\Laravel\Tests\TestCase; @@ -31,17 +32,26 @@ public function testDate(): void $model->update(['dateField' => now()->subDay()]); self::assertInstanceOf(Carbon::class, $model->dateField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('dateField')); self::assertEquals(now()->subDay()->startOfDay()->format('Y-m-d H:i:s'), (string) $model->dateField); $model->update(['dateField' => new DateTime()]); self::assertInstanceOf(Carbon::class, $model->dateField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('dateField')); self::assertEquals(now()->startOfDay()->format('Y-m-d H:i:s'), (string) $model->dateField); $model->update(['dateField' => (new DateTime())->modify('-1 day')]); self::assertInstanceOf(Carbon::class, $model->dateField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('dateField')); self::assertEquals(now()->subDay()->startOfDay()->format('Y-m-d H:i:s'), (string) $model->dateField); + + $refetchedModel = Casting::query()->find($model->getKey()); + + self::assertInstanceOf(Carbon::class, $refetchedModel->dateField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('dateField')); + self::assertEquals(now()->subDay()->startOfDay()->format('Y-m-d H:i:s'), (string) $refetchedModel->dateField); } public function testDateAsString(): void diff --git a/tests/Casts/DatetimeTest.php b/tests/Casts/DatetimeTest.php index dc2bdd877..022ed3535 100644 --- a/tests/Casts/DatetimeTest.php +++ b/tests/Casts/DatetimeTest.php @@ -7,6 +7,7 @@ use Carbon\CarbonImmutable; use DateTime; use Illuminate\Support\Carbon; +use MongoDB\BSON\UTCDateTime; use MongoDB\Laravel\Tests\Models\Casting; use MongoDB\Laravel\Tests\TestCase; @@ -27,11 +28,13 @@ public function testDatetime(): void $model = Casting::query()->create(['datetimeField' => now()]); self::assertInstanceOf(Carbon::class, $model->datetimeField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('datetimeField')); self::assertEquals(now()->format('Y-m-d H:i:s'), (string) $model->datetimeField); $model->update(['datetimeField' => now()->subDay()]); self::assertInstanceOf(Carbon::class, $model->datetimeField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('datetimeField')); self::assertEquals(now()->subDay()->format('Y-m-d H:i:s'), (string) $model->datetimeField); } @@ -40,6 +43,7 @@ public function testDatetimeAsString(): void $model = Casting::query()->create(['datetimeField' => '2023-10-29']); self::assertInstanceOf(Carbon::class, $model->datetimeField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('datetimeField')); self::assertEquals( Carbon::createFromTimestamp(1698577443)->startOfDay()->format('Y-m-d H:i:s'), (string) $model->datetimeField, @@ -48,6 +52,7 @@ public function testDatetimeAsString(): void $model->update(['datetimeField' => '2023-10-28 11:04:03']); self::assertInstanceOf(Carbon::class, $model->datetimeField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('datetimeField')); self::assertEquals( Carbon::createFromTimestamp(1698577443)->subDay()->format('Y-m-d H:i:s'), (string) $model->datetimeField, @@ -82,6 +87,7 @@ public function testImmutableDatetime(): void $model->update(['immutableDatetimeField' => '2023-10-28 11:04:03']); self::assertInstanceOf(CarbonImmutable::class, $model->immutableDatetimeField); + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('immutableDatetimeField')); self::assertEquals( Carbon::createFromTimestamp(1698577443)->subDay()->format('Y-m-d H:i:s'), (string) $model->immutableDatetimeField, diff --git a/tests/Casts/DecimalTest.php b/tests/Casts/DecimalTest.php index 535328fe4..f69d24d62 100644 --- a/tests/Casts/DecimalTest.php +++ b/tests/Casts/DecimalTest.php @@ -4,10 +4,18 @@ namespace MongoDB\Laravel\Tests\Casts; +use Illuminate\Support\Exceptions\MathException; +use MongoDB\BSON\Binary; use MongoDB\BSON\Decimal128; +use MongoDB\BSON\Int64; +use MongoDB\BSON\Javascript; +use MongoDB\BSON\UTCDateTime; +use MongoDB\Laravel\Collection; use MongoDB\Laravel\Tests\Models\Casting; use MongoDB\Laravel\Tests\TestCase; +use function now; + class DecimalTest extends TestCase { protected function setUp(): void @@ -21,25 +29,103 @@ public function testDecimal(): void { $model = Casting::query()->create(['decimalNumber' => 100.99]); - self::assertInstanceOf(Decimal128::class, $model->decimalNumber); + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Decimal128::class, $model->getRawOriginal('decimalNumber')); self::assertEquals('100.99', $model->decimalNumber); $model->update(['decimalNumber' => 9999.9]); - self::assertInstanceOf(Decimal128::class, $model->decimalNumber); + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Decimal128::class, $model->getRawOriginal('decimalNumber')); self::assertEquals('9999.90', $model->decimalNumber); + + $model->update(['decimalNumber' => 9999.00000009]); + + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Decimal128::class, $model->getRawOriginal('decimalNumber')); + self::assertEquals('9999.00', $model->decimalNumber); } public function testDecimalAsString(): void { $model = Casting::query()->create(['decimalNumber' => '120.79']); - self::assertInstanceOf(Decimal128::class, $model->decimalNumber); + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Decimal128::class, $model->getRawOriginal('decimalNumber')); self::assertEquals('120.79', $model->decimalNumber); $model->update(['decimalNumber' => '795']); - self::assertInstanceOf(Decimal128::class, $model->decimalNumber); + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Decimal128::class, $model->getRawOriginal('decimalNumber')); self::assertEquals('795.00', $model->decimalNumber); + + $model->update(['decimalNumber' => '1234.99999999999']); + + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Decimal128::class, $model->getRawOriginal('decimalNumber')); + self::assertEquals('1235.00', $model->decimalNumber); + } + + public function testDecimalAsDecimal128(): void + { + $model = Casting::query()->create(['decimalNumber' => new Decimal128('100.99')]); + + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Decimal128::class, $model->getRawOriginal('decimalNumber')); + self::assertEquals('100.99', $model->decimalNumber); + + $model->update(['decimalNumber' => new Decimal128('9999.9')]); + + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Decimal128::class, $model->getRawOriginal('decimalNumber')); + self::assertEquals('9999.90', $model->decimalNumber); + } + + public function testOtherBSONTypes(): void + { + $modelId = $this->setBSONType(new Int64(100)); + $model = Casting::query()->find($modelId); + + self::assertIsString($model->decimalNumber); + self::assertIsInt($model->getRawOriginal('decimalNumber')); + self::assertEquals('100.00', $model->decimalNumber); + + // Update decimalNumber to a Binary type + $this->setBSONType(new Binary('100.1234', Binary::TYPE_GENERIC), $modelId); + $model->refresh(); + + self::assertIsString($model->decimalNumber); + self::assertInstanceOf(Binary::class, $model->getRawOriginal('decimalNumber')); + self::assertEquals('100.12', $model->decimalNumber); + + $this->setBSONType(new Javascript('function() { return 100; }'), $modelId); + $model->refresh(); + self::expectException(MathException::class); + self::expectExceptionMessage('Unable to cast value to a decimal.'); + $model->decimalNumber; + self::assertInstanceOf(Javascript::class, $model->getRawOriginal('decimalNumber')); + + $this->setBSONType(new UTCDateTime(now()), $modelId); + $model->refresh(); + self::expectException(MathException::class); + self::expectExceptionMessage('Unable to cast value to a decimal.'); + $model->decimalNumber; + self::assertInstanceOf(UTCDateTime::class, $model->getRawOriginal('decimalNumber')); + } + + private function setBSONType($value, $id = null) + { + // Do a raw insert/update, so we can enforce the type we want + return Casting::raw(function (Collection $collection) use ($id, $value) { + if (! empty($id)) { + return $collection->updateOne( + ['_id' => $id], + ['$set' => ['decimalNumber' => $value]], + ); + } + + return $collection->insertOne(['decimalNumber' => $value])->getInsertedId(); + }); } } diff --git a/tests/Casts/EncryptionTest.php b/tests/Casts/EncryptionTest.php new file mode 100644 index 000000000..0c40254f1 --- /dev/null +++ b/tests/Casts/EncryptionTest.php @@ -0,0 +1,102 @@ +make(Encrypter::class) + ->decryptString( + $model->getRawOriginal($key), + ); + } + + public function testEncryptedString(): void + { + $model = Casting::query()->create(['encryptedString' => 'encrypted']); + + self::assertIsString($model->encryptedString); + self::assertEquals('encrypted', $model->encryptedString); + self::assertNotEquals('encrypted', $model->getRawOriginal('encryptedString')); + self::assertEquals('encrypted', $this->decryptRaw($model, 'encryptedString')); + + $model->update(['encryptedString' => 'updated']); + self::assertIsString($model->encryptedString); + self::assertEquals('updated', $model->encryptedString); + self::assertNotEquals('updated', $model->getRawOriginal('encryptedString')); + self::assertEquals('updated', $this->decryptRaw($model, 'encryptedString')); + } + + public function testEncryptedArray(): void + { + $expected = ['foo' => 'bar']; + $model = Casting::query()->create(['encryptedArray' => $expected]); + + self::assertIsArray($model->encryptedArray); + self::assertEquals($expected, $model->encryptedArray); + self::assertNotEquals($expected, $model->getRawOriginal('encryptedArray')); + self::assertEquals($expected, Json::decode($this->decryptRaw($model, 'encryptedArray'))); + + $updated = ['updated' => 'array']; + $model->update(['encryptedArray' => $updated]); + self::assertIsArray($model->encryptedArray); + self::assertEquals($updated, $model->encryptedArray); + self::assertNotEquals($updated, $model->getRawOriginal('encryptedArray')); + self::assertEquals($updated, Json::decode($this->decryptRaw($model, 'encryptedArray'))); + } + + public function testEncryptedObject(): void + { + $expected = (object) ['foo' => 'bar']; + $model = Casting::query()->create(['encryptedObject' => $expected]); + + self::assertIsObject($model->encryptedObject); + self::assertEquals($expected, $model->encryptedObject); + self::assertNotEquals($expected, $model->getRawOriginal('encryptedObject')); + self::assertEquals($expected, Json::decode($this->decryptRaw($model, 'encryptedObject'), false)); + + $updated = (object) ['updated' => 'object']; + $model->update(['encryptedObject' => $updated]); + self::assertIsObject($model->encryptedObject); + self::assertEquals($updated, $model->encryptedObject); + self::assertNotEquals($updated, $model->getRawOriginal('encryptedObject')); + self::assertEquals($updated, Json::decode($this->decryptRaw($model, 'encryptedObject'), false)); + } + + public function testEncryptedCollection(): void + { + $expected = collect(['foo' => 'bar']); + $model = Casting::query()->create(['encryptedCollection' => $expected]); + + self::assertInstanceOf(Collection::class, $model->encryptedCollection); + self::assertEquals($expected, $model->encryptedCollection); + self::assertNotEquals($expected, $model->getRawOriginal('encryptedCollection')); + self::assertEquals($expected, collect(Json::decode($this->decryptRaw($model, 'encryptedCollection'), false))); + + $updated = collect(['updated' => 'object']); + $model->update(['encryptedCollection' => $updated]); + self::assertIsObject($model->encryptedCollection); + self::assertEquals($updated, $model->encryptedCollection); + self::assertNotEquals($updated, $model->getRawOriginal('encryptedCollection')); + self::assertEquals($updated, collect(Json::decode($this->decryptRaw($model, 'encryptedCollection'), false))); + } +} diff --git a/tests/Casts/IntegerTest.php b/tests/Casts/IntegerTest.php index f1a11dba5..99cb0cd14 100644 --- a/tests/Casts/IntegerTest.php +++ b/tests/Casts/IntegerTest.php @@ -51,4 +51,22 @@ public function testIntAsString(): void self::assertIsInt($model->intNumber); self::assertEquals(9, $model->intNumber); } + + public function testIntAsFloat(): void + { + $model = Casting::query()->create(['intNumber' => 1.0]); + + self::assertIsInt($model->intNumber); + self::assertEquals(1, $model->intNumber); + + $model->update(['intNumber' => 2.0]); + + self::assertIsInt($model->intNumber); + self::assertEquals(2, $model->intNumber); + + $model->update(['intNumber' => 9.6]); + + self::assertIsInt($model->intNumber); + self::assertEquals(9, $model->intNumber); + } } diff --git a/tests/Casts/JsonTest.php b/tests/Casts/JsonTest.php index 99473c5d8..2b8759dd6 100644 --- a/tests/Casts/JsonTest.php +++ b/tests/Casts/JsonTest.php @@ -25,9 +25,17 @@ public function testJson(): void self::assertIsArray($model->jsonValue); self::assertEquals(['g' => 'G-Eazy'], $model->jsonValue); - $model->update(['jsonValue' => json_encode(['Dont let me go' => 'Even the longest of nights turn days'])]); + $model->update(['jsonValue' => ['Dont let me go' => 'Even the longest of nights turn days']]); self::assertIsArray($model->jsonValue); + self::assertIsString($model->getRawOriginal('jsonValue')); self::assertEquals(['Dont let me go' => 'Even the longest of nights turn days'], $model->jsonValue); + + $json = json_encode(['it will encode json' => 'even if it is already json']); + $model->update(['jsonValue' => $json]); + + self::assertIsString($model->jsonValue); + self::assertIsString($model->getRawOriginal('jsonValue')); + self::assertEquals($json, $model->jsonValue); } } diff --git a/tests/Casts/ObjectTest.php b/tests/Casts/ObjectTest.php index 3217b23fc..e45b736e0 100644 --- a/tests/Casts/ObjectTest.php +++ b/tests/Casts/ObjectTest.php @@ -21,11 +21,13 @@ public function testObject(): void $model = Casting::query()->create(['objectValue' => ['g' => 'G-Eazy']]); self::assertIsObject($model->objectValue); + self::assertIsString($model->getRawOriginal('objectValue')); self::assertEquals((object) ['g' => 'G-Eazy'], $model->objectValue); $model->update(['objectValue' => ['Dont let me go' => 'Even the brightest of colors turn greys']]); self::assertIsObject($model->objectValue); + self::assertIsString($model->getRawOriginal('objectValue')); self::assertEquals((object) ['Dont let me go' => 'Even the brightest of colors turn greys'], $model->objectValue); } } diff --git a/tests/Casts/StringTest.php b/tests/Casts/StringTest.php index 120fb9b19..67ed7227d 100644 --- a/tests/Casts/StringTest.php +++ b/tests/Casts/StringTest.php @@ -7,6 +7,8 @@ use MongoDB\Laravel\Tests\Models\Casting; use MongoDB\Laravel\Tests\TestCase; +use function now; + class StringTest extends TestCase { protected function setUp(): void @@ -27,5 +29,11 @@ public function testString(): void self::assertIsString($model->stringContent); self::assertEquals("Losing hope, don't mean I'm hopeless And maybe all I need is time", $model->stringContent); + + $now = now(); + $model->update(['stringContent' => $now]); + + self::assertIsString($model->stringContent); + self::assertEquals((string) $now, $model->stringContent); } } diff --git a/tests/Models/Casting.php b/tests/Models/Casting.php index 9e232cf15..f44f08a62 100644 --- a/tests/Models/Casting.php +++ b/tests/Models/Casting.php @@ -32,6 +32,10 @@ class Casting extends Eloquent 'datetimeWithFormatField', 'immutableDatetimeField', 'immutableDatetimeWithFormatField', + 'encryptedString', + 'encryptedArray', + 'encryptedObject', + 'encryptedCollection', ]; protected $casts = [ @@ -52,5 +56,9 @@ class Casting extends Eloquent 'datetimeWithFormatField' => 'datetime:j.n.Y H:i', 'immutableDatetimeField' => 'immutable_datetime', 'immutableDatetimeWithFormatField' => 'immutable_datetime:j.n.Y H:i', + 'encryptedString' => 'encrypted', + 'encryptedArray' => 'encrypted:array', + 'encryptedObject' => 'encrypted:object', + 'encryptedCollection' => 'encrypted:collection', ]; } diff --git a/tests/QueueTest.php b/tests/QueueTest.php index c23e711ab..2236fba1b 100644 --- a/tests/QueueTest.php +++ b/tests/QueueTest.php @@ -27,6 +27,8 @@ public function setUp(): void // Always start with a clean slate Queue::getDatabase()->table(Config::get('queue.connections.database.table'))->truncate(); Queue::getDatabase()->table(Config::get('queue.failed.table'))->truncate(); + + Carbon::setTestNow(Carbon::now()); } public function testQueueJobLifeCycle(): void @@ -147,7 +149,6 @@ public function testQueueDeleteReserved(): void public function testQueueRelease(): void { - Carbon::setTestNow(); $queue = 'test'; $delay = 123; Queue::push($queue, ['action' => 'QueueRelease'], 'test');