讓測試更方便系列:快速建立資料

wkan發表於2020-05-17

在寫測試的過程中,經常需要建立很多測試資料。根據 Laravel 的文件,我們使用模型工廠方法建立資料。但是預設的模型工廠建立資料的方法只有單條資料,或者相同的多條資料,像這樣:

factory(Product::class)->create(['title' => '商品標題']);

而我們的需求經常是建立多條不同的資料,比如這樣:

factory(Product::class)->create(['title' => '商品標題1']);
factory(Product::class)->create(['title' => '商品標題2']);
factory(Product::class)->create(['title' => '商品標題3']);

這種情況我們需要寫很多條,但是隻有一個引數不同,所以我們可以寫一個方法來直接建立多條資料:

create(string $model, array $attrs): Collection;

第一個引數是要建立的 Model 類,第二個引數是一個二維陣列,可以包含多個模型資料,根據第二個引數的資料條數建立對應數量的模型,然後作為一個集合返回。

當然更進一步,當我們需要像以前那樣建立多條一樣的資料時,也可以 傳入一個數量來告訴方法,我們需要建立多少條資料,所以方法變成了這樣:

create(string $model, array $attrs, $amount = null): Collection;

如果有了這個方法,那麼上面建立多條資料寫法就可以變成:

create(Product::class, [
    ['title' => '商品標題1'],
    ['title' => '商品標題2'],
    ['title' => '商品標題3'],
]);

是不是看上去要簡單很多呢。

當然,別忘了我們還有 make 方法,來建立模型,但是不插入資料庫,所以要有一個一樣簽名的 make 方法。

最終我們可以得到這樣的實現:

function make($model, $attrs = [], $amount = null)
{
    return _makeOrCreate($model, $attrs, $amount, 'make');
}

function create($model, $attrs = [], $amount = null)
{
    return _makeOrCreate($model, $attrs, $amount, 'create');
}

function _makeOrCreate($model, $attrs, $amount, $method)
{
    if (! isset($attrs[0]) || ! is_array($attrs[0])) {
        return factory($model, $amount)->$method($attrs);
    }
    $lastSubAttrs = [];
    $results = collect();
    if ($amount === null) {
        $amount = count($attrs);
    }
    for ($i = 0; $i < $amount; $i++) {
        if (isset($attrs[$i])) {
            $lastSubAttrs = $attrs[$i];
        }
        $results->push(factory($model)->$method($lastSubAttrs));
    }

    return $results;
}

可以把這些方法放在一個 tests/helper.php 檔案裡,然後在 compsoer.jsonautoload-dev 屬性中引用,這樣就可以在測試中愉快的使用了。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

Laravel YES !

相關文章