#laravel #testing #mocking
Вопрос:
Привет, последний вопрос по разгадке кода — я пытаюсь создавать тесты, которые издеваются над определенными классами, но изо всех сил пытаюсь заставить свою первую попытку работать. Похоже, что в тесте используется не макет, а реальный класс.
Есть три вопроса:
- Что мне нужно изменить, чтобы заставить это работать и использовать макет?
- Работает ли макет для всего тестируемого приложения или только для тестируемого класса?
- Если бы я хотел вернуть массив значений, нужно ли мне просто создать массив с ожидаемыми значениями, чтобы тестируемый класс мог использовать эти возвращенные данные?
Итак, вот класс, над которым я хочу поиздеваться:
<?php
namespace AppWedleagueUtility;
use AppLibrariesUtilitiesFolderUtility;
use AppWedleagueLeagueTableLeagueTableInterface;
use PDF;
/**
* Class PDFGenerator
* Generates a PDF based on a league
* @package AppLibrariesHelpers
*/
class PDFGenerator
{
use FolderUtility;
/**
* set the folder location for the generated pdf
* @var string
*/
private string $storageFolder = 'pdf';
private string $path;
private LeagueTableInterface $leagueTable;
/**
* PDFGenerator constructor.
*/
public function __construct(LeagueTableInterface $leagueTable)
{
$this->path = storage_path('app/' . $this->storageFolder);
$this->setUp();
$this->leagueTable = $leagueTable;
}
/**
* @return BarryvdhDomPDFPDF
*/
public function createLeaguePDF()
{
$this->leagueTable->getLeagueTable();
error_reporting(E_ALL ^ E_DEPRECATED);
return PDF::loadView($this->leagueTable->getViewPath(), $this->leagueTable->getViewData())
->setOptions(['fontSubsetting' => true])
->setPaper('a4', 'landscape')
->save(storage_path('app/pdf/' . $this->leagueTable->getLeagueType() . '_league_update.pdf'));
}
private function setUp()
{
$this->checkFolderExists($this->path);
}
}
Вот класс, который я пытаюсь протестировать, который использует этот класс:
<?php
namespace AppJobs;
use AppWedleagueUtilityPDFGenerator;
use AppMailMailEclecticUpdate;
use AppModelsLeague;
use AppWedleagueLeagueTableEclecticLeagueTable;
use Exception;
use IlluminateBusQueueable;
use IlluminateContractsQueueShouldQueue;
use IlluminateFoundationBusDispatchable;
use IlluminateQueueInteractsWithQueue;
use IlluminateQueueSerializesModels;
use IlluminateSupportFacadesLog;
use IlluminateSupportFacadesMail;
/**
* Class ProcessSendEclecticUpdate
* @package AppJobs
*/
class ProcessSendEclecticUpdateEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* The number of times the job may be attempted.
*
* @var int
*/
public $tries = 3;
/**
* The number of seconds the job can run before timing out.
*
* @var int
*/
public $timeout = 240;
private League $league;
public function __construct(League $league)
{
$this->league = $league;
}
public function handle()
{
if (!$this->league || $this->league->league_type !== 'eclectic') {
throw new Exception("Error Processing the job - league not found or invalid league", 1);
}
$PDFGenerator = new PDFGenerator(new EclecticLeagueTable($this->league));
$PDFGenerator->createLeaguePDF();
$this->league->player()->get()->each(function ($player) {
if ($player->contactEmail) {
Mail::to($player->contactEmail)
->queue(new MailEclecticUpdate(
$this->league
));
}
});
Log::info('Eclectic League update issued');
}
}
and here’s the basics of the test:
<?php
namespace TestsJobs;
use AppJobsProcessSendEclecticUpdateEmail;
use AppMailMailEclecticUpdate;
use AppModelsLeague;
use AppModelsUser;
use AppWedleagueUtilityPDFGenerator;
use IlluminateFoundationTestingRefreshDatabase;
use IlluminateFoundationTestingWithFaker;
use IlluminateSupportFacadesBus;
use IlluminateSupportFacadesMail;
use TestsTestCase;
/**
* Class ProcessSendEclecticUpdateTest
* @package TestsJobs
*/
class ProcessSendEclecticUpdateTest extends TestCase
{
use RefreshDatabase;
use WithFaker;
private $user;
private $adminUser;
protected function setUp(): void
{
parent::setUp();
$this->seed();
$this->adminUser = User::factory()->create(['admin' => 1]);
}
/**
* @test
* @covers ProcessSendEclecticUpdateEmail::handle
* @description:
*/
public function testHandle()
{
$mock = $this->mock(AppWedleagueUtilityPDFGenerator::class);
$mock->shouldReceive('createLeaguePDF')->once();
$this->app->instance(PDFGenerator::class, $mock);
Mail::fake();
$this->withoutExceptionHandling();
$league = League::find(27);
$players = $league->player()
->get()
->filter(function ($player){
return $player->contactEmail;
});
ProcessSendEclecticUpdateEmail::dispatch($league);
Mail::assertQueued(MailEclecticUpdate::class, $players->count());
}
}
The response I get from the test is:
MockeryExceptionInvalidCountException : Method createLeaguePDF(<Any Arguments>) from Mockery_2_App_Wedleague_Utility_PDFGenerator should be called
exactly 1 times but called 0 times.
I know this is not using the mock due to the length of time the test takes as it produces a PDF
Any ideas how I can get this to work — it’s mocking me!!! 🙂