Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mencipta Fasad Boleh Diuji dalam Laravel

Mencipta Fasad Boleh Diuji dalam Laravel

Barbara Streisand
Barbara Streisandasal
2024-09-29 06:08:30262semak imbas

Creating a Testable Facade in Laravel

Berikut ialah helaian tipu tentang cara menjadikan kelas perkhidmatan ringkas anda lebih berguna dengan menambahkan suntikan pergantungan, fasad dan cara menukar dengan mudah dengan palsu.

Rangkanya mudah:

  • Kelas perkhidmatan asal
  • Buat kontrak yang dipatuhi oleh kelas perkhidmatan
  • Dalam penyedia perkhidmatan, daftarkan kelas perkhidmatan dalam bekas
  • Buat fasad
  • Buat pelaksanaan palsu kontrak yang boleh ditukar untuk ujian

Kelas perkhidmatan asal

Inilah kelas perkhidmatan asal kami yang kami mulakan (maaf kerana tidak mempunyai contoh yang menarik, tetapi tidak semestinya perlu mencipta satu untuk ini).

<?php

namespace App\Foo;

class FooService
{
    public function foo(): string
    {
        return 'bar';
    }

    public function fizz(): string
    {
        return 'buzz';
    }
}

Kontrak itu

Pertama, kami harus membuat kontrak supaya kami dapat memastikan bahawa perkhidmatan palsu kami dan perkhidmatan asal kami memenuhi jangkaan. Serta sebarang pelaksanaan masa hadapan.

<?php

namespace App\Foo\Contracts;

interface Foo
{
    public function foo(): string;

    public function fizz(): string;
}

Jangan lupa pastikan perkhidmatan melaksanakannya.

<?php

namespace App;

use App\Foo\Contracts\Foo;

class FooService implements Foo
{
   // ...
}

Mengikat pada bekas

Seterusnya, kami harus mengikat pelaksanaan konkrit dengan kontrak dalam pembekal perkhidmatan kami.

<?php

namespace App\Providers;

use App\Foo\Contracts\Foo;
use App\FooService;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        $this->app->bind(Foo::class, FooService::class);
    }

   // ...
}

Fasad

Kini, kami boleh mencipta kelas fasad kami.

<?php

namespace App\Foo\Facades;

use Illuminate\Support\Facades\Facade;

/**
* @method static string foo(): string
* @method static string fizz(): string
*/
class Foo extends Facade
{
    protected static function getFacadeAccessor(): string
    {
        return \App\Foo\Contracts\Foo::class;
    }
}

Fasad hanya memerlukan nama pengikat yang akan ditarik dari bekas untuk dikembalikan daripada getFacadeAccessor. Dalam kes kami, itulah nama kontrak yang pada masa ini mempunyai perkhidmatan kami terikat kepadanya.

Perhatikan bahawa jika anda mahukan sokongan IDE, anda perlu mentakrifkan semula tandatangan kaedah dalam blok dokumen di atas kelas.

Pada ketika ini, kami boleh menggunakan fasad kami.

Penggunaan

<?php

namespace App\Http\Controllers;

use App\Foo\Facades\Foo;

class FooController extends Controller
{
    public function index()
    {
        return response()->json([
            'foo' => Foo::foo(),
        ]);
    }
}

Sebagai alternatif, kami juga boleh menyuntiknya sebagai pergantungan.

<?php

namespace App\Http\Controllers;

use App\Foo\Contracts;

class FooController extends Controller
{
   public function __construct(protected Foo $foo) {}

    public function index()
    {
        return response()->json([
            'foo' => $this->foo->foo(),
        ]);
    }
}

Memalsukan fasad

Laravel sering menawarkan cara yang kemas untuk memalsukan fasadnya dengan mudah, mis. Acara::fake(). Kita boleh melaksanakannya sendiri.

Apa yang perlu kami lakukan ialah mencipta pelaksanaan kontrak kami yang palsu, kemudian tambahkan kaedah palsu pada fasad kami.

<?php

namespace App\Foo;

use App\Foo\Contracts\Foo;

class FakeFooService implements Foo
{
    public function __construct(public Foo $actual) {}

    public function foo(): string
    {
        return 'fake';
    }

    public function fizz(): string
    {
        return 'very fake';
    }
}

Dalam pelaksanaan palsu kami, kami juga membuat rujukan awam kepada kelas konkrit "sebenar".

Dan inilah pelaksanaan palsu fasad kami. Anda boleh lihat kami menggunakan rujukan itu kepada sebenar.

<?php

namespace App\Foo\Facades;

use App\Foo\FakeFooService;
use Illuminate\Support\Facades\Facade;

/**
* @method static string foo(): string
* @method static string fizz(): string
*/
class Foo extends Facade
{
    public static function fake()
    {
        $actual = static::isFake()
            ? static::getFacadeRoot()->actual
            : static::getFacadeRoot();

        tap(new FakeFooService($actual), function ($fake) {
            static::swap($fake);
        });
    }

   // ...
}

Ujian asas

Sekarang mari tulis ujian pantas yang sesuai dengan contoh pengawal yang kami buat di atas.

<?php

namespace Tests\Feature;

use App\Foo\Facades\Foo;
use Illuminate\Testing\Fluent\AssertableJson;
use Tests\TestCase;

class FooTest extends TestCase
{
    public function test_foo(): void
    {
        $response = $this->get('/');

        $response->assertJson(fn (AssertableJson $json)
            => $json->where('foo', 'bar'));
    }

    public function test_fake_foo(): void
    {
        Foo::fake();

        $response = $this->get('/');

        $response->assertJson(fn (AssertableJson $json)
            => $json->where('foo', 'fake'));
    }
}

Ujian tidak berguna tetapi ia menunjukkan betapa mudahnya untuk menggunakan palsu kami. Dalam test_fake_foo kita mendapat foo=fake manakala test_foo mengembalikan foo=bar.

Mengambil ujian lebih lanjut

Perkara yang menyeronokkan tentang palsu ialah dalam pelaksanaan palsu kami, kami boleh menambah kaedah tambahan untuk menguji apa sahaja yang kami rasa berguna. Sebagai contoh, kita boleh menampar pembilang dalam kaedah foo palsu kita yang meningkat setiap kali kita memanggil foo. Kemudian kita boleh menambah kaedah yang dipanggil assertFooCount di mana kita boleh menegaskan bahawa kaedah itu dipanggil seberapa banyak kali yang kita jangkakan.

<?php

namespace App\Foo;

use App\Foo\Contracts\Foo;
use Illuminate\Testing\Assert;

class FakeFooService implements Foo
{
    public int $fooCount = 0;

    public function __construct(public Foo $actual) {}

    public function foo(): string
    {
        $this->fooCount++;

        return 'fake';
    }

    public function fizz(): string
    {
        return 'very fake';
    }

    public function assertFooCount(int $count)
    {
        Assert::assertSame($this->fooCount, $count);
    }
}

Seperti yang anda lihat, kami menggunakan IlluminateTestingAssert Laravel untuk membuat penegasan. Kemudian ujian kami boleh kelihatan seperti ini.

public function test_incrementor(): void
{
    Foo::fake();

    Foo::foo();
    Foo::foo();
    Foo::foo();

    Foo::assertFooCount(3); // pass!
}

Itu sahaja!

Bukan semua perkara memerlukan fasad, tetapi apabila anda membina alatan/pakej yang digunakan secara dalaman, fasad selalunya merupakan corak yang kukuh untuk dipercayai.

Berikut ialah repo dengan semua kod: https://github.com/ClintWinter/laravel-facade-example

Atas ialah kandungan terperinci Mencipta Fasad Boleh Diuji dalam Laravel. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn