PHPUnit check method invoked multiple times with multiple parameters - phpunit

I have the following class:
class Foo
{
public function importBars(array $array)
{
foreach ($array as $key => $value) {
$this->importBar($key, $value);
}
}
public function importBar($key, $value)
{
// do stuff
}
}
I need to test that importBar is called count($array) times, and that it's called with the right parameters. Using $this->at() is not an option, as the order of the $array elements might change. I have:
public function testImportBars(array $array)
{
// Mock invocation ...
$logicalOrs = array();
foreach ($array as $sku => $value) {
$logicalOrs[] = $this->logicalOr($this->equalTo($key), $this->equalTo($value));
}
$mock->expects($this->exactly(count($array)))
->method('importBar')
->with(call_user_func_array(array($this, 'logicalOr'), $logicalOrs));
}
Which passes the tests. However, when I deliberately make it fail:
foreach ($array as $sku => $value) {
$logicalOrs[] = $this->logicalOr($this->equalTo($key), $this->equalTo(null));
}
... it still passes. It only fails if the $key is incorrect:
foreach ($array as $sku => $value) {
$logicalOrs[] = $this->logicalOr($this->equalTo(null), $this->equalTo(null));
}
... which suggests PHPUnit is only checking if the first parameter passed to Foo::importBar() is correct.
Is there a way to tell PHPUnit to verify arguments to methods when there is more than one?

After some trial and error, here is the closest solution I've come up with:
$rows = array();
foreach ($array as $key => $value) {
$rows[] = array($key, $value);
}
$method = $mock->expects($this->exactly(count($array)))
->method('importBar');
call_user_func_array(array($method, 'withConsecutive'), $rows);
See: http://phpunit.de/manual/4.1/en/test-doubles.html#test-doubles.mock-objects

Related

Get scale unit at cart

I need the scale unit at my cart to show it at the frontend, but I do not get it.
I tried by a subscriber and to load the product, but I do not get the selected scale unit.
public function onLoadCart(OffcanvasCartPageLoadedEvent $event)
{
foreach ($event->getPage()->getCart()->getLineItems() as $item) {
$product = $this->productRepository->search(
new Criteria(
[
$item->getId()
]
),
$event->getContext()
)->first();
dd($product);
}
}
The term scale unit offset me a little at first. I assume you are looking for the ProductUnit. The ProductUnit is an association, and you need to add this to your criteria.
public function onLoadCart(OffcanvasCartPageLoadedEvent $event)
{
foreach ($event->getPage()->getCart()->getLineItems() as $item) {
$criteria = new Criteria(
[
$item->getId()
]
);
$criteria->addAssociation('unit');
$product = $this->productRepository->search(
$criteria,
$event->getContext()
)->first();
dd($product);
}
}

Maatwebsite 3.1 import, Queue does not work

My file is excel .xlsx contains more than 20,000 rows, im using Centos 7 with Nginx web server. When i upload a small size file with few rows it works but when i introduce ShouldQueue and WithChunkReading interfaces it fails even if the file is small. Please I need help. Thanks for your time
Here is the error in a log file
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php
[2019-07-11 14:48:47] development.ERROR: [0] File "/tmp/laravel-excel-4noteGu1gFjJoFClKJQsLw8SgDShm1nd.xlsx" does not exist. on line 344 of file vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php
[2019-07-11 14:48:47] development.ERROR: [0] File "/tmp/laravel-excel-4noteGu1gFjJoFClKJQsLw8SgDShm1nd.xlsx" does not exist. on line 344 of file vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php
Here is a queue error
[2019-07-12 10:11:47][532] Processing: Maatwebsite\Excel\Jobs\QueueImport
[2019-07-12 10:11:47][532] Processed: Maatwebsite\Excel\Jobs\QueueImport
[2019-07-12 10:11:47][533] Processing: Maatwebsite\Excel\Jobs\ReadChunk
[2019-07-12 10:11:47][534] Processing: Maatwebsite\Excel\Jobs\ReadChunk
[2019-07-12 10:11:47][535] Processing: Maatwebsite\Excel\Jobs\ReadChunk
[2019-07-12 10:11:47][535] Failed: Maatwebsite\Excel\Jobs\ReadChunk
Here is my controller function
public function store(Request $request)
{
Excel::import(new HsCodeImport(),"650.xlsx",'local');
return redirect()->back()->withFlashSuccess(__('label.app_success'));
}
Here is my Import file on App\Imports\HsCodeImport.php
<?php
namespace App\Imports;
use App\Exceptions\GeneralException;
use App\Models\Application\Hscode;
use App\Models\ReceiptCode\ReceiptCode;
use Carbon\Carbon;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
class HsCodeImport implements ToCollection, WithHeadingRow, ShouldQueue, WithChunkReading
{
use Importable;
protected $receiptCode;
protected $chunk = 500;
protected $hscode_key = 'hscode';
protected $description_key = 'description';
protected $regulatory_status_key = 'regulatory_status';
protected $comment_key = 'comment';
protected $headings = ['hscode','description','regulatory_status','comment'];
public function __construct(/*ReceiptCode $receiptCode*/)
{
// $this->receiptCode = $receiptCode;
}
/**
* #param Collection $collection
* #throws GeneralException
*/
public function collection(Collection $collection)
{
/*fetching the first Collection*/
$columns = $collection->first();
if (!$columns->has($this->headings)) {
/*When file has different headings*/
} else {
/*When the file has expected headings*/
/*Truncate temp table*/
DB::table('hs_code_temps')->truncate();
/*Counting rows on a file*/
$original_file_rows_count = $collection->count();
/*Chunk the file data according #var $chunk*/
$chunks = $collection->chunk($this->chunk);
/*read each chunks insert into Temporary table and validate to get if there is error in each row*/
$chunks->each(function ($item) {
/*Iterate on each chunk*/
$item->toArray();
foreach ($item as $row) {
/* start: Validating row entries */
$error_report = "";
$error = 0;
foreach ($row as $key => $value) {
if (trim($key) == $this->hscode_key) {
if (trim($value) == "" Or $value == NULL) {
$error = 1;
$error_report = $error_report . trans('exceptions.backend.upload.entries', ['column' => $key, 'entry' => $value]) . ", \r\n";
$row[$key] = NULL;
}
} elseif (trim($key) == $this->description_key) {
if (trim($value) == "" Or $value == NULL) {
$error = 1;
$error_report = $error_report . trans('exceptions.backend.upload.entries', ['column' => $key, 'entry' => $value]) . ", \r\n";
$row[$key] = NULL;
}
} elseif (trim($key) == $this->regulatory_status_key) {
if (trim($value) == "" Or $value == NULL) {
$error = 1;
$error_report = $error_report . trans('exceptions.backend.upload.entries', ['column' => $key, 'entry' => $value]) . ", \r\n";
$row[$key] = NULL;
}
}
}
/*Inserting into Temp table*/
DB::table('hs_code_temps')->insert([
'code' => $row[$this->hscode_key],
$this->description_key => $row[$this->description_key],
$this->regulatory_status_key => $row[$this->regulatory_status_key],
$this->comment_key => $row[$this->comment_key],
'receipt_code_id' => 1/*$receiptCode->id*/,
'error' => $error,
'error_report' => $error_report,
'created_at' => Carbon::now(),
]);
/* end: Validating row entries*/
}
});
/*compare total rows with no error to total rows of the file*/
$total_temp_rows_count = DB::table('hs_code_temps')->whereError(0)->count();
if ($total_temp_rows_count != $original_file_rows_count) {
/*When there is error and rows are not equal*/
} else {
/*When there is no error*/
$originalHsCode = new Hscode();
$temp_table = DB::table('hs_code_temps')->get(['code', $this->description_key, $this->regulatory_status_key, $this->comment_key])/*->toArray()*/;
/*Iterate throw the rows in a temp row*/
foreach ($temp_table as $object) {
/*copy data from temp table to origin table*/
$originalHsCode->create(get_object_vars($object));
}
/*Truncate temp table*/
DB::table('hs_code_temps')->truncate();
}
}
}
public function headings(): array
{
return ['HSCode','Description','Regulatory_Status','Comment'];
}
/*public function sheets(): array
{
}*/
public function chunkSize(): int
{
return 500;
}
public function batchSize(): int
{
return 500;
}
}
I expect the job to run a large data to a chunk to be processed
pass false as third parameter to chunk() to disable queuing
$data = [];
Excel::filter('chunk')->load($path)->chunk(1000, function ($results) use (&$data) {
foreach ($results as $row) {
$data[] = $row;
}
}, $shouldQueue = false);
return $data;
I have a similar problem when deplying to heroku ,that points to a problem with the path.:
`ERROR: [0] File "/tmp/laravel-excel-4noteGu1gFjJoFClKJQsLw8SgDShm1nd.xlsx"
does not exist. on line 344 of file
vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php`
laravel-excel defines local_path variable in config/excel.php, so try changing the path here or check your public_path() where you are geting the problem.
in my case the excemption saved in table failde_jobs is:
"exception": """ InvalidArgumentException: File "/app/storage/framework/laravel-excel/laravel-excel-aCnUQTJT7ADvAnrf1AOEcaCBPLjhauij" does not exist. in /app/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php:135\n
have been trying to see how to change sot that it does not go in the app folder..

Multiple select DQL

I have:
if (count($data['paymentTypes'])<5) {
$arr = array();
foreach (array_values($data['paymentTypes']) as $value) { $arr[]=$value->getId(); }
$query = $query->leftJoin('p.payments','g')->where('g.id IN(:num)')->setParameter('num', $arr);
}
if (count($data['expertise']->toArray())>0) {
$arr = array();
foreach (array_values($data['expertise']->toArray()) as $value) { $arr[]=$value->getId(); }
$query = $query->leftJoin('p.expertise','g')->where('g.id IN(:num)')->setParameter('num', $arr);
}
How may I stop the query from breaking in case both statements are true? I would expect leftjoins and wheres to congregate but they throw an exception instead. What is the cleanest way of accomplishing this?
Use different alias and parameter name in the second part than in the first.

Passing argument to function in Wordpress

I have following function:
public function id_callback($idnumber){}
And I call it this way:
for($i = 1; $i <= $fieldcount; $i++)
{
add_settings_field(
'id' . $i,
'ID' . $i,
array( $this, 'id_callback' ),
'my-setting-admin',
'setting_section_id'
);
}
How can I pass $i as an argument to id_callback?
Thanks in advance.
Your code is a little abstract, as it does not come with a specific context, however i'll try to help you. You basically have to create a variable and a method that sets that variable. Then you should use that method to change the variable in the for loop. Here is a quick example of what i'm talking about (i've created an example class that replicates a simple use case):
<?php
class Example_Callback {
public $id_callback;
public function set_id_callback($id_callback) {
$this->id_callback = $id_callback;
}
public function do_something() {
// here is your $i:
$callback_id = $this->id_callback;
// here you can do something with your $callback_id
}
public function test() {
$fieldcount = 5; // usually this should come from somewhere
for($i = 1; $i <= $fieldcount; $i++) {
$this->set_id_callback($i);
add_settings_field(
'id' . $i,
'ID' . $i,
array( $this, 'do_something' ),
'my-setting-admin',
'setting_section_id'
);
}
}
}
$callback = new Example_Callback();
$callback->test();
?>

A different service for my Flex app using Zend_Amf

I have an iterator service that works fine already and returns a correctly structured values to my flex application through my Zend Amf server
$contacts = array();
mysql_connect( 'localhost', 'root', 'test' );
mysql_select_db( 'test' );
$res = mysql_query( 'SELECT * FROM contact' );
while( $contact = mysql_fetch_assoc($res) ) {
$contacts []= $contact;
}
return $contacts;
However I would like to adjust this so that I can leverage my MVC structure and achieve the same results.
I have placed an excerpt that can be brought to working condition
$contacts = array();
$table = new Model_DbTable_Contact();
$result = $table->fetchAll();
//Return an array to be consumed by my flex application
foreach ($result as $row)
{
/*do something*/
}
return $contacts;
You'll want to look into ValueObjects. Zend_Amf supports those, and it's a good idea to use that. That way you can have objects that are native to both PHP and Flex.
$server->setClassMap('ContactVO', 'Contact');
Your Flex would then have a class:
[Bindable]
[RemoteClass(alias="Contact")]
public class ContactVO
{
}
Would tell your server that you're going to map your Contact class to ContactVO in Flex.
then you could do:
$data = array();
foreach ($result as $row)
{
$data[] = new Contact($row);
//assuming the Contact constructor parses the array data
}
return $data;
and your Contact objects would get to Flex as ContactVO objects
So here I have a function in the logical model for a database table:
public function fetchAll() {
$resultSet = $this->getDbTable()->fetchAll();
$entries = array();
foreach( $resultSet as $row ) {
$entry = new Model_ClosingData();
$entry->setId($row->id)
->setContractMonth($row->monthId)
->setCommodity($row->commodityId)
->setDate($row->date)
->setPrice($row->price)
->setVolume($row->volume)
->setOutstandingInterest($row->outstandingInterest);
$entries[] = $entry;
}
return $entries;
}

Resources