Mencipta Fasad Boleh Diuji dalam Laravel

Barbara Streisand
Lepaskan: 2024-09-29 06:08:30
asal
260 orang telah melayarinya

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';
    }
}
Salin selepas log masuk

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;
}
Salin selepas log masuk

Jangan lupa pastikan perkhidmatan melaksanakannya.

<?php

namespace App;

use App\Foo\Contracts\Foo;

class FooService implements Foo
{
   // ...
}
Salin selepas log masuk

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);
    }

   // ...
}
Salin selepas log masuk

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;
    }
}
Salin selepas log masuk

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(),
        ]);
    }
}
Salin selepas log masuk

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(),
        ]);
    }
}
Salin selepas log masuk

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';
    }
}
Salin selepas log masuk

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);
        });
    }

   // ...
}
Salin selepas log masuk

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'));
    }
}
Salin selepas log masuk

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);
    }
}
Salin selepas log masuk

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!
}
Salin selepas log masuk

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!

sumber:dev.to
Kenyataan Laman Web ini
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
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!