Jak namockovat model

Než začneme tak bych rád upozornil, že pokud chceme namockovat model, tak to může naznačovat, že je něco špatně. Přinejmenším architektura kódu. Ideálně bychom neměli mock modelu nikdy potřebovat a naopak využívat factory pro vytvoření dummy modelu. Nicméně nežijeme v ideální světě a občas to prostě potřebujeme. Například v mém případě jsem to potřeboval kvůli tomu, že model využíval připojení do jiné databáze a jelikož testy běžely v transakci kde se používala jiná databáze, tak jsem nebyl schopen se připojit. Nezbývalo mi nic jiného než namockovat. Ale opět, vše vzniklo díky tomu, že od začátku byla špatně postavena architektura a namísto připojení do jiné databáze se to mělo vyřešit např. přes API.

Mock modelu

Namockovat model je vcelku jednoduché, kdy využijeme knihovnu Mockery:

$modelMock = \Mockery::mock('alias:App\Models\Post');
$modelMock->shouldReceive('where')
    ->times(3)
    ->andReturn(\Mockery::self())
    ->shouldReceive('count')
    ->andReturn(1);

Zde jsme si vytvořili mock modelu, kde je důležitý alias. Když použijete alias:, Mockery vytvoří mock třídy a zároveň definuje alias pro tuto třídu v PHP, což znamená, že kdykoliv bude aplikace chtít tuto třídu načíst, místo toho získá mock. V našem případě Mockery vytvoří mock třídy App\Models\Post. Pokud aplikace někde poté pokusí vytvořit novou instanci této třídy, místo toho získá vytvořený mock.

Dále už se jedná o klasickou syntaxi Mockery, kde si definujeme metody a návratové hodnoty podle toho co reálně na modelu voláme.

Tento způsob namockování modelu je vhodný tehdy, pokud si potřebujete nasimulovat model a pouze jeho metody. V případě, že potřebujete z něho vytáhnout data, např. $post->id, pak musíte definovat i toto chování. Což v případě že potřebujete vytáhnout více sloupců může být dost otravné vše nasimulovat. Pak je lepší přejít k jinému řešení a využít klasické factory modelu.

Mock konstanty v mock modelu

Na závěr ještě jeden příklad v případě, kdy si chcete namockovat statickou konstantu v dříve namockovaném modelu:

\Mockery::getConfiguration()->setConstantsMap([
    'App\Models\Post' => [
        'NEWS_TYPE' => 'news',
    ]
]);