Laravel - phpunit array assertion - php

I am trying to write a phpunit test so I can test that I'm getting the correct assertion, this test i currently have which is passing and works as intended.
/**
#test
*/
$filmInfo = $this->postRequest();
$this->assertFilm($this->requestData, $filmInfo['id']);
$film = Film::findOrFail($filmInfo['id']);
$this->assertEquals('LOTR', $filmInfo['name']);
$this->assertEquals('Film about a ring', $filmInfo['description']);
$this->assertEquals('Fantasy', $filmInfo['genre']['main']);
$this->assertEquals('Adventure', $filmInfo['genre']['sub']);
}
This is the request data array it is referring to:
private function requestData(): array
{
return [
'name' => 'LOTR',
'description' => 'Film about a ring',
'main' => 'Fantasy',
'sub' => 'Adventure',
];
}
This test works fine and it passing but I want to test it within one assertion like so:
$this->assertEquals([
'name' => 'LOTR',
'description' => 'Film about a ring',
'genre' => [
'main' => 'Fantasy',
'sub' => 'Adventure'
]
,
], $filmInfo);
But I keep getting an error that the 2 arrays I'm asserting are not matching, do you guys have an idea on what could be causing this?

Just like what the PHPUnit said, your array aren't matching. Your array should match with all values in $filmInfo array.
From your code, we can guessing that you aren't comparing the id. Maybe you can try this code:
$this->assertEquals(array_merge($filmInfo, [
'name' => 'LOTR',
'description' => 'Film about a ring',
'genre' => [
'main' => 'Fantasy',
'sub' => 'Adventure'
],
]), $filmInfo);

Related

Returning empty object in Laravel resource instead of null

I do have a resource (DeviceResource) in my Laravel API which contains another resource (SimcardResource). There is a OnetoOne relationship between those resources but sometimes a device has no associated simcard.
If this is the case my DeviceResource returns for the simcard null instead of an empty json object.
I do need an empty json object because I present information called from my API in my Vue frontend by accessing an object e.g. like device.simcard.phone_number
My DeviceResource class looks like this:
public function toArray($request)
{
return [
'id' => $this->resource->id,
'model' => $this->resource->model,
'device_name' => $this->resource->device_name,
'operating_system' => $this->resource->operating_system,
'os_version' => $this->resource->os_version,
'emei' => $this->resource->emei,
'device_password' => $this->resource->device_password,
'purchase_date' => $this->resource->purchase_date,
'associated_worker' => $this->resource->associated_worker,
'remarks' => $this->resource->remarks,
'device_status_id' => $this->resource->device_status_id,
// 'simcard' => $this->resource->simcard ?: (object)[],
'simcard' => SimcardResource::make($this->whenLoaded('simcard')) ?: (object)[],
];
}
The commented section:
'simcard' => $this->resource->simcard ?: (object)[]
Works perfectly but returns all fields from my simcard table but I only need fields defined in my SimcardResource class so I tried the following:
'simcard' => SimcardResource::make($this->whenLoaded('simcard')) ?: (object)[]
But it still returns null instead of an empty json object.
Okay maybe its not the best solution but my DeviceResource class now looks like this:
public function toArray($request)
{
if (is_null($this->resource->simcard)) {
return [
'id' => $this->resource->id,
'model' => $this->resource->model,
'device_name' => $this->resource->device_name,
'operating_system' => $this->resource->operating_system,
'os_version' => $this->resource->os_version,
'emei' => $this->resource->emei,
'device_password' => $this->resource->device_password,
'purchase_date' => $this->resource->purchase_date,
'associated_worker' => $this->resource->associated_worker,
'remarks' => $this->resource->remarks,
'device_status_id' => $this->resource->device_status_id,
'simcard' => (object) [],
];
} else {
return [
'id' => $this->resource->id,
'model' => $this->resource->model,
'device_name' => $this->resource->device_name,
'operating_system' => $this->resource->operating_system,
'os_version' => $this->resource->os_version,
'emei' => $this->resource->emei,
'device_password' => $this->resource->device_password,
'purchase_date' => $this->resource->purchase_date,
'associated_worker' => $this->resource->associated_worker,
'remarks' => $this->resource->remarks,
'device_status_id' => $this->resource->device_status_id,
// 'simcard' => $this->resource->simcard ?: (object)[],
'simcard' => SimcardResource::make($this->whenLoaded('simcard')),
];
}
}
It is Laravel resource default behaviour that if you do not have any data than resource will also return you the null resource object. You have to manage it yourself in other way like by defining each parameter has null value that's it.
Laravel introduce best ways,for example whenLoaded,but try this
... ?? json_encode(new stdClass)

How to access json in an array?

I am trying to access json in a nested array but it is not working yet.
I am developing in laravel an have this
public function rave(Request $request){
$vars = [
'id' => Request::get('id'),
'txref' => Request::get('txRef'),
'flwref' => Request::get('flwRef'),
'created_at' => Request::get('createdAt'),
'amount' => Request::get('amount'),
'status' => Request::get('status'),
'name' => Request::get('fullName'),
'email' => Request::get('customer'),
];
I am able to get and display all in view but name and email which comes back in the response as
"customer":{
"id":15672,
"phone":"7667866 ",
"fullName":"john doe ",
"customertoken":null,
"email":"kely#gmail.com",
"createdAt":"2019-06-09T08:28:56.000Z",
"updatedAt":"2019-06-09T08:28:56.000Z",
"deletedAt":null,
"AccountId":33519
},
How do I access the data under customer because this
'name' => Request::get('fullName'),
'email' => Request::get('customer'),
doesn't seem to work like the others
You use Request $request as function parameter,
and check output of
echo $request->input('customer.fullName');
echo $request->input('customer.email');

Lumen 5.4: PHPUnit: How to test authorisation?

I am working on an ecommerce project, a generic book shop.
I started out with a Test Driven approach, and I adhered to it fully till now.
Different endpoints on this Lumen Microservice project have been successfully tested earlier to make sure they do CRUD operations. However, as I have to protect the Create, Update and Delete method with token authorisation, I am quite confused how to introduce tests for authorisation.
As of now this is my testing structure:
tests/app/Exceptions/HandlerTest.php
tests/app/Http/Controllers/BooksControllerTest.php
The tests are for index, show, store, update, delete. This is one of the tests:
public function testStoreBookByPost()
{
$book = factory('App\Book')->make();
$this->post(
'/books',
[
'isbn' => $book->isbn,
'title' => $book->title,
'description' => $book->description,
'author' => $book->author,
'image' => $book->image,
'price' => $book->price,
'slug' => $book->slug
]
);
$this
->seeJson(
[
'created' => true
]
)
->seeInDatabase(
'books',
[
'title' => $book->title
]
);
}
I had earlier separated Exception Handler tests, similarly I would prefer to separate the AuthControllerTest to AuthControllerTest.php.
What is the best way to do this?
Do I need to write the authorisation tests by refactoring all the BooksControllerTest?
Or should I just test for issuing of token and inability to manipulate database? Would that be fine?
Short answer: I needed to write the authorisation tests by refactoring all the BooksControllerTest
Long answer: I found out a fantastic way of logging in dummy users during testing.
With that I have created this method.
public function loginWithUserGetJWT()
{
$user = factory('App\User')->create(
[
'password' => bcrypt('366643') // random password
]
);
$content = $this
->post(
'/auth/login',
[
'email' => $user->email,
'password' => '366643'
]
)
->seeStatusCode(200)
->response->getContent();
$token = json_decode($content)->token;
return $token;
}
And I am reusing this method in all the test cases, like so:
public function testStoreBookByPost()
{
$token = $this->loginWithUserGetJWT();
$book = factory('App\Book')->make();
$this->post(
'/books',
[
'isbn' => $book->isbn,
'title' => $book->title,
'description' => $book->description,
'author' => $book->author,
'image' => $book->image,
'price' => $book->price,
'slug' => $book->slug,
'token' => $token
]
);
$this
->seeJson(
[
'created' => true
]
)
->seeInDatabase(
'books',
[
'title' => $book->title
]
);
}

Merge the inner array to the parent array using hash of cakephp

I have the following array
$array['projects'] = [
'name1' => [
'task' => [
'tags' => ['value1', 'value2'],
'email' => 'email2',
'description' => 'mpla'
],
'email' => 'email1',
'tags' => ['value1', 'value3'],
'title' => 'mpla'
]
];
Is there anyway I could use the Hash class of CakePHP 3 or maybe another class of CakePHP framework to achieve the following result:
$array['projects'] = [
'name1' => [
'email' => 'email2',
'tags' => ['value1', 'value2'],
'title' => 'mpla'
'desciption' => 'mpla'
]
];
If you also know anyother package that it can handle arrays and get my job done it will do.
Not sure that this can be easily achieved using Cake's Hash utility. You can easily extract the array items indexed by task using combine(), but not sure how you would then go about extracting the title values and combining those with the other array elements using Hash:-
Hash::combine($array, 'projects.{s}', 'projects.{s}.task');
Perhaps the simplest solution is to use a foreach loop like this:-
$data = [];
foreach ($array['projects'] as $value) {
$data['projects'] = $value['task'] + ['title' => $value['title']];
}

test if array contains value using PHPUnit

I created this array of objects:
$ad_1 = new AdUnit(array('id' => '1', 'name' => 'Ad_1', 'description' => 'great ad', 'code' => 'alpha', 'widget_id' => '123'));
$ad_2 = new AdUnit(array('id' => '2', 'name' => 'Ad_2', 'description' => 'good ad', 'code' => 'delta', 'widget_id' => '456'));
$ad_3 = new AdUnit(array('id' => '3', 'name' => 'Ad_3', 'description' => 'bad ad', 'code' => 'sigma', 'widget_id' => '789'));
$adUnitArr = array($ad_1, $ad_2, $ad_3);
and i want to check that a random ad i got from a function exists in the array. the code to get the ad looks like this:
$fixture = new AdGroup();
$fixture->setAds($adUnitArr);
$randad = $fixture->getRandomAd();
now i want to check if the array contains the random ad i received, what i was able to do like this:
$this->assertEquals(in_array($randad, $adUnitArr), 1); //check if ad in array
but my question is, is there an assert or some other way to check this thing better than the way i did it?? i tried using assertArrayHasKey but i got the following error:
PHPUnit_Framework_Exception: Argument #1 (No Value) of PHPUnit_Framework_Assert::assertArrayHasKey() must be a integer or string
any idea please? thx
Try the assertContains method:
$this->assertContains( $randad, $adUnitArr );

Categories