ホームページ > バックエンド開発 > PHPチュートリアル > PHP: 嘲笑すべきですか、それともやめるべきですか?

PHP: 嘲笑すべきですか、それともやめるべきですか?

Barbara Streisand
リリース: 2024-12-11 10:36:12
オリジナル
817 人が閲覧しました

PHP: Should I mock or should I go?

要するにモック

モックは、実際のオブジェクトの動作をテストすることを目的としています。

依存関係をシミュレートするため、単体テストの速度が大幅に低下する可能性がある外部リソースを呼び出す必要はありません。

期待を定義し、それを検証できます。

たとえば、メソッドが特定の回数呼び出されたり、特定のパラメータを使用して呼び出されたりするようにすることができます。

use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    public function testMockExample(): void
    {
        $depencencyMock = $this->createMock(MyDependency::class);

        $dependencyMock->expects($this->exactly(2))
              ->method('someMethod')
              ->with('some parameter');

        $classToTest = new ClassToTest($dependencyMock);
   }
}
ログイン後にコピー
ログイン後にコピー

戻り値

willReturn() は戻り値の型との互換性を保証します:

// In code
class MyClass {
    public function getNum(): int {
    }
}

// In tests
$myClassMock = $this->createMock(MyClass::class);
$myClassMock->expects($this->once())
            ->method('getNum')
            ->willReturn(2);
ログイン後にコピー

入力パラメータに基づいて動的な動作をテストしたい場合は、willReturnCallback を使用することもできます。

避けるべき悪い習慣

モックは実際の動作を模倣するだけなので、要点を見逃しがちです。よくある悪い習慣について話し合いましょう:

期待せずに値を返す

❌ それはやめてください:

$colorServiceMock = $this->createMock(ColorService::class);
$colorServiceMock->method('hexToName')
     ->willReturn('red');

$color = (new MyClass($colorServiceMock))->getColorName('ff0000');
ログイン後にコピー

✅ 代わりに、いくつかの期待を追加します:

$colorServiceMock->expects($this->once())
     ->method('hexToName')
     ->with('00f00')
     ->willReturn('green');

$color = (new MyClass($colorServiceMock))->getColorName('00f00');
ログイン後にコピー

モックの目的はインタラクションを検証することであることを忘れないでください。

インターフェイスではなく実際のオブジェクトをモックする

SomeInterface を実装する MyClass をテストしてみましょう。

❌ それはやめてください:

$myclassMock = $this->createMock(MyClass::class);
ログイン後にコピー

✅ 代わりに、インターフェースをモックします:

$myclassMock = $this->createMock(SomeInterface::class);
ログイン後にコピー

モックは動作に焦点を当てます。コントラクトではなく実装を変更することになっているため、通常、インターフェイスは変更されません。

オーバーモックテスト

Tomas Votruba がこの問題を美しく説明しています: オーバーモックされたテストから価値を抽出する 5 つの方法

モックを使用して悪い設計慣行を隠す

コンポーネント間の緊密な結合を無視するのは簡単です:

$productRepositoryMock = $this->createMock(ProductRepository::class);
$invoiceRepositoryMock = $this->createMock(InvoiceRepository::class);
$emailServiceMock = $this->createMock(EmailService::class);

$overComplexService = new OverComplexService($productRepositoryMock, $invoiceRepositoryMock, $emailServiceMock);
ログイン後にコピー

上記の例は関心事の分離を破壊しており、モックはその悪い習慣を永続させています。

モックのみに依存する

モックは強力なツールですが、単体テストだけでは十分ではありません。他にもさまざまなタイプのテスト (統合、e2e など) が必要です。

モックの不適切な使用を見分ける方法

悪い習慣に加えて、プロジェクト内でモックが誤用または過剰に使用されていることを示す兆候が他にもあります。

  • テストは現実世界のシナリオを反映しておらず、本番環境の重要な問題を見落としています
  • テストと実装の間に密接な関係があるため、関連するモックが頻繁に更新されます
  • テストが複雑すぎるため、読み取りや保守が難しくなります

モックとスタブ

Martin Fowler は、モックがスタブではない理由を説明する素晴らしい投稿を書きました。

これらを使用できる具体的な状況を見てみましょう:

モックを使用する場合

モックがより意味のあるテストケースをいくつか示します:

  • クラスがその依存関係とどのように対話するかをテストする必要があります
  • 特定のメソッドが異なるパラメータで複数回呼び出される複雑なシーケンスをチェックする必要があります

スタブを使用する場合

PHPUnit を使用してスタブを非常に簡単に作成できます。

use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    public function testMockExample(): void
    {
        $depencencyMock = $this->createMock(MyDependency::class);

        $dependencyMock->expects($this->exactly(2))
              ->method('someMethod')
              ->with('some parameter');

        $classToTest = new ClassToTest($dependencyMock);
   }
}
ログイン後にコピー
ログイン後にコピー

スタブがより意味のあるテストケースをいくつか示します:

  • 相互作用を検証することなく、コードの出力または状態をテストしたい
  • 実際のデータベースを操作せずにいくつかの計算をテストする必要があります

一言で言えば、スタブは実際のオブジェクトの動作をチェックすることを目的としたものではなく、状態をチェックすることを目的としています。

微調整

単体テストの主な目的は、各単体/コンポーネントが期待どおりに動作することを確認することですが、実際のコードに加えてそれらのテストも保守する必要があります。

スタブはテストのセットアップを簡素化し、メソッド呼び出しや対話を追跡する必要がない単純なシナリオでは非常に効率的です。

一部のテストに焦点を当てておくことで、不必要な複雑さを防ぐことができます。

まとめ

モックはメソッド呼び出しとそのパラメータを追跡できます。

実際の動作を表す値を返すことを忘れないでください。そうしないと、誤った安心感を抱いてしまう可能性があります。

メンテナンスに不必要な複雑さを避けるために、モックは控えめに使用する必要があります。

以上がPHP: 嘲笑すべきですか、それともやめるべきですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート