[ [ '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); } } }