Skip to content

Instantly share code, notes, and snippets.

@celyes
Created March 18, 2025 09:44
Show Gist options
  • Save celyes/78e3b83bc7c13ac1d730e0dc8b83f8e1 to your computer and use it in GitHub Desktop.
Save celyes/78e3b83bc7c13ac1d730e0dc8b83f8e1 to your computer and use it in GitHub Desktop.
<?php
namespace Tests\Unit\Services;
use App\Jobs\ProcessProductImage;
use App\Models\Product;
use App\Services\SpreadsheetService;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Queue;
use Mockery;
use Tests\TestCase;
class SpreadsheetServiceTest extends TestCase
{
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
/**
* @return array
*/
public function spreadsheetDataProvider()
{
return [
'valid data' => [
[
'product_code' => 'ABC123',
'quantity' => 10,
],
false, // Validation fails
true, // Product creation
true, // Job dispatched
],
'missing product_code' => [
[
'quantity' => 10,
],
true, // Validation fails
false, // Product creation
false, // Job dispatched
],
'invalid quantity' => [
[
'product_code' => 'DEF456',
'quantity' => 0,
],
true, // Validation fails
false, // Product creation
false, // Job dispatched
],
];
}
/**
* @dataProvider spreadsheetDataProvider
*/
public function testProcessSpreadsheet($rowData, $validationFails, $productCreated, $jobDispatched)
{
$importerMock = $this->mockImporter($filePath = 'path/to/spreadsheet.xlsx', $rowData);
$this->mockValidator($rowData, $validationFails);
$this->mockProductCreation($rowData, $productCreated);
Queue::fake();
$service = new SpreadsheetService();
$service->processSpreadsheet($filePath);
$this->assertJobDispatch($rowData, $jobDispatched);
}
/**
* @param string $filePath
* @param array $rowData
* @return \Mockery\MockInterface
*/
protected function mockImporter(string $filePath, array $rowData)
{
$importerMock = Mockery::mock();
$this->app->instance('importer', $importerMock);
$importerMock->shouldReceive('import')
->once()
->with($filePath)
->andReturn([$rowData]);
return $importerMock;
}
/**
* @param array $rowData
* @param bool $validationFails
* @return void
*/
protected function mockValidator(array $rowData, bool $validationFails)
{
$validatorMock = Mockery::mock();
$validatorMock->shouldReceive('fails')
->andReturn($validationFails);
$validatorMock->shouldReceive('validated')
->andReturn($rowData);
Validator::shouldReceive('make')
->once()
->with($rowData, [
'product_code' => 'required|unique:products,code',
'quantity' => 'required|integer|min:1',
])
->andReturn($validatorMock);
}
/**
* @param array $rowData
* @param bool $productCreated
* @return void
*/
protected function mockProductCreation(array $rowData, bool $productCreated)
{
if ($productCreated) {
$productMock = (object) $rowData;
Product::shouldReceive('create')
->once()
->with($rowData)
->andReturn($productMock);
} else {
Product::shouldReceive('create')
->never();
}
}
/**
* @param array $rowData
* @param bool $jobDispatched
* @return void
*/
protected function assertJobDispatch(array $rowData, bool $jobDispatched)
{
if ($jobDispatched) {
Queue::assertPushed(ProcessProductImage::class, function ($job) use ($rowData) {
return $job->product->product_code === $rowData['product_code'];
});
} else {
Queue::assertNotPushed(ProcessProductImage::class);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment