自訂期望
Pest 的期望值 API 預設功能強大,但有時你可能需要在測試之間重複編寫相同的期望值。這種情況下,針對你的特定需求建立自訂期望值會非常有用。
自訂期望值通常定義在 tests/Pest.php
檔案中,但你也可以將它們整理在不同的 tests/Expectations.php
檔案中,以利於維護。若要在 Pest 中建立自訂期望值,將 extend()
方法連結在 expect()
函式上,但不用提供任何期望值。
例如,假設你正在測試一個數字公用程式函式庫,你需要經常斷言數字是否在給定的範圍內。這種情況下,你可以建立一個名為 toBeWithinRange()
的自訂期望值
1// Pest.php or Expectations.php... 2expect()->extend('toBeWithinRange', function (int $min, int $max) { 3 return $this->toBeGreaterThanOrEqual($min) 4 ->toBeLessThanOrEqual($max); 5}); 6 7// Tests/Unit/ExampleTest.php 8test('numeric ranges', function () { 9 expect(100)->toBeWithinRange(90, 110);10});
雖然使用者通常在自訂期望值中利用 Pest 內建的期望值,就像在 toBeWithinRange()
範例中展示的那樣,但有時你可能需要直接存取期望值來執行你自己的自訂期望值邏輯。這種情況下,你可以透過 $this->value
屬性存取傳遞給 expect($value)
的期望值。
1expect()->extend('toBeWithinRange', function (int $min, int $max) {2 echo $this->value; // 1003});
當然,你可能希望使用者可以將期望值與你的自訂期望值「連結」。若要達成此事,請確保你的自訂期望值包含 return $this
陳述式。
1// Pest.php or Expectations.php... 2expect()->extend('toBeWithinRange', function (int $min, int $max) { 3 // Assertions based on `$this->value` and the given arguments... 4 5 return $this; // Return this, so another expectations can chain this one... 6}); 7 8// Tests/Unit/ExampleTest.php 9test('numeric ranges', function () {10 expect(100)11 ->toBeInt()12 ->toBeWithinRange(90, 110)13 ->to...14});
攔截期望值
雖然這被認為是進階做法,但透過 intercept()
方法,你可以用自己的實作覆寫現有的期望值。使用此方法時,如果期望值是指定類型,現有的期望值將被完全取代。例如,你可以取代 toBe()
期望值,以檢查 Illuminate\Database\Eloquent\Model
类型的兩個物件是否具有相同的 id
。
1use Illuminate\Database\Eloquent\Model; 2use App\Models\User; 3 4// tests/Pest.php or tests/Expectations.php 5expect()->intercept('toBe', Model::class, function(Model $expected) { 6 expect($this->value->id)->toBe($expected->id); 7}); 8 9// tests/Feature/ExampleTest.php10test('models', function () {11 $userA = User::find(1);12 $userB = User::find(1);13 14 expect($userA)->toBe($userB);15});
與將字串類型傳遞為 intercept()
方法的第二個引數不同,你也可以傳遞一個封閉,用以決定是否覆寫核心期望值。
1expect()->intercept('toBe', fn (mixed $value) => is_string($value), function (string $expected, bool $ignoreCase = false) {2 if ($ignoreCase) {3 assertEqualsIgnoringCase($expected, $this->value);4 } else {5 assertSame($expected, $this->value);6 }7});
管道預期
您可能會想執行 Pest 的內建預期之一,但在特定條件下納入客製化預期邏輯。在這些情況下,您可以使用 pipe()
方法。例如,如果您給定的值是一個 Eloquent 模型,我們可能想要客製化 toBe()
預期的行為。
1use Illuminate\Database\Eloquent\Model; 2use App\Models\User; 3 4expect()->pipe('toBe', function (Closure $next, mixed $expected) { 5 if ($this->value instanceof Model) { 6 return expect($this->value->id)->toBe($expected->id); 7 } 8 9 return $next(); // Run to the original, built-in expectation...10});
如所示範,建立自訂預期可以顯著簡化您的程式碼,無需重複邏輯來驗證您的測試是否按預期進行。在下一章中,我們將探討 Pest 提供的其他 CLI 選項:CLI API 參考