Stub

stub

Permasalahan Unit Test

Kadang membuat unit test untuk sebuah class bukanlah hal yang mudah, apalagi jika ternyata class tersebut tergantung dengan object lain.

Apalagi jika ternyata object yang dibutuhkan ternyata tergantung dengan object lain lagi.

Hal seperti ini akan sangat menyulitkan saat membuat unit test.

Sebagai contoh kita akan coba membuat studi kasus sederhana membuat class yang kompleks.

Product

<?php

namespace BikinBalik\Test;

class Product
{
    private string $id, $name, $description;
    private int $price, $quantity;

    /**
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * @param string $id
     */
    public function setId(string $id): void
    {
        $this->id = $id;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName(string $name): void
    {
        $this->name = $name;
    }

    /**
     * @return string
     */
    public function getDescription(): string
    {
        return $this->description;
    }

    /**
     * @param string $description
     */
    public function setDescription(string $description): void
    {
        $this->description = $description;
    }

    /**
     * @return int
     */
    public function getPrice(): int
    {
        return $this->price;
    }

    /**
     * @param int $price
     */
    public function setPrice(int $price): void
    {
        $this->price = $price;
    }

    /**
     * @return int
     */
    public function getQuantity(): int
    {
        return $this->quantity;
    }

    /**
     * @param int $quantity
     */
    public function setQuantity(int $quantity): void
    {
        $this->quantity = $quantity;
    }


}

generate getter dan setter dari properties

Product Repository

<?php

namespace BikinBalik\Test;

interface ProductRepository
{
    function save(Product $product): Product;

    function delete(Product $product): Void;

    function findById(string $id): ?Product;

    function findAll(): array;
}

product repository

Product Service

<?php

namespace BikinBalik\Test;

class ProductService
{
    public function __construct(private ProductRepository $repository)
    {
    }

    public function register(Product $product): Product
    {
        if ($this->repository->findById($product->getId()) != null)
        {
            throw new \Exception("Product is already exists");
        }

        return $this->repository->save($product);
    }

}

product services

Stub

Saat akan membuat test untuk sebuah class, dan ternyata class tersebut butuh dependency object lain, maka kita bisa membuat object pengganti yang bisa kita konfigurasi agar sesuai dengan keinginan kita.

Teknik ini dinamakan stubbing, dan object pengganti yang kita buat disebut stub.

PHPUnit mendukung pembuatan object stub secara mudah hanya dengan menggunakan function createStub(className) yang terdapat di class TestCase.

method createStub() secara otomatis akan membuat object class atau interface yang kita inginkan dengan default implementation.

Membuat Stub

Membuat stub

Konfigurasi Stub

Secara default, semua function di stub akan mengembalikan null jika nullable return type, atau default value jika tipe data primitive, atau stub lain jika tipe data class.

Biasanya kita akan melakukan konfigurasi stub terlebih dahulu sebelum kita menggunakan stub.

Dengan begitu, kita bisa memprediksi tingkah laku stub tersebut sesuai dengan konfigurasi yang kita buat.

Melakukan konfigurasi stub sederhananya hanya memberi tahu stub, jika sebuah function di eksekusi, kita ingin mengembalikan data apa.

Invocation Stubber

Stub memiliki function yang bernama method(name), dimana dia akan mengembalikan InvocationStubber.

Dengan InvocationStubber, kita bisa mengatur hasil kembalian dari function yang dipanggil di stub.

https://github.com/sebastianbergmann/phpunit/blob/master/src/Framework/MockObject/Builder/InvocationStubber.php .

interface InvocationStubber

Secara Defaut Mengmbalikan Nilai NULL

default mengembalikan nilai null

hasil, mengembalikan nilai null

Kode Konfigurasi Stub

konfigurasi stub

hasil konfigurasi stub

Kode Konfigurasi Stub dengan Map

kode konfigurasi stub dengan map

hasil konfigurasi stub dengan map

Kode Konfigurasi Stub dengan Callback

konfigurasi stub dengan callback

hasil konfigurasi stub dengan callback

Integrasi Dengan Stub

Sekarang kita sudah tahu cara menggunakan stub.

Jika kita akan membuat uni test untuk sebuah class, dan ternyata class tersebut membutuhkan object lain, maka disarankan untuk menggunakan stub.

Hal ini agar tingkah laku stub bisa kita konfigurasi, sehingga perubahan yang terjadi di class asli stub nya tidak akan mempengaruhi unit test kita.

Kode Product Service Test Sukses

Kode Product Service Test Sukses

hasil Kode Product Service Test Sukses

Kode Product Service Test Gagal

Kode Product Service Test Gagal

hasil Kode Product Service Test Gagal
Next Post Previous Post
No Comment
Add Comment
comment url