'How to get view data during unit testing in Laravel
I would like to check the array given to a view in a controller function has certain key value pairs. How do I do this using phpunit testing?
//my controller I am testing
public function getEdit ($user_id)
{
$this->data['user'] = $user = \Models\User::find($user_id);
$this->data['page_title'] = "Users | Edit";
$this->data['clients'] = $user->account()->firstOrFail()->clients()->lists('name', 'id');
$this->layout->with($this->data);
$this->layout->content = \View::make('user/edit', $this->data);
}
//my test
public function testPostEdit (){
$user = Models\User::find(parent::ACCOUNT_1_USER_1);
$this->be($user);
$response = $this->call('GET', 'user/edit/'.parent::ACCOUNT_1_USER_1);
//clients is an array. I want to get this
//array and use $this->assetArrayContains() or something
$this->assertViewHas('clients');
$this->assertViewHas('content');
}
Solution 1:[1]
TL;DR; Try $data = $response->getOriginalContent()->getData();
I found a better way to do it. I wrote a function in the TestCase which returns the array I want from the view data.
protected function getResponseData($response, $key){
$content = $response->getOriginalContent();
$data = $content->getData();
return $data[$key]->all();
}
So to get a value from the $data object I simply use $user = $this->getResponseData($response, 'user');
Solution 2:[2]
Inside a test case use:
$data = $this->response->getOriginalContent()->getData();
Example:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class HomeTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$data = $this->response->getOriginalContent()->getData();
// do your tests on the data
}
}
Example dumping data so you can see what in data(array) passed to view:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class HomeTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$data = $this->response->getOriginalContent()->getData();
dd($data);
}
}
Should get something back like what's in image:
Solution 3:[3]
I managed it by doing it in a messy way. I used assertViewHas:
$this->assertViewHas('clients', array('1' => 'Client 1', '6' => 'Client2'));
Solution 4:[4]
So looking at how assertViewHas is implemented HERE it looks like, what the method does, is access the view's data after this call:
$response = $this->client->getResponse()->original;
In your code, the line:
$response = $this->call('GET', 'user/edit/'.parent::ACCOUNT_1_USER_1);
essentially returns the same thing as the line above it, namely a \Illuminate\Http\Response (which extends the symfony component \HttpFoundation\Response)
So, inside the assertViewHas function it looks like laravel accesses the data using $response->$key, so I would try to access the clients and 'content' variables through the $response object.
If that doesn't work try searching around the TestCase file in the Laravel framework ... I'm sure the answer is in there somewhere. Also try to dump the $response object and see what it looks like, there should be some clues there.
The first thing I would try, though, is accessing your data through the $response object.
Solution 5:[5]
You can access data in the response and it can be checked..
public function testSimpleLastProducts() {
$res = $this->call('GET', '/');
$this->assertResponseOk();
$this->assertViewHas('lastProducts');
$lastProductOnView = $res->original['lastProducts'];
$this->assertEquals(6, count($lastProductOnView));
}
Solution 6:[6]
This worked for me:
$response->getSession()->get("errors")
And from there you can check the contents of the message box for whatever error you might want verify.
Solution 7:[7]
Looking for something like this in 2019, I got:
$response->getData()->data[0]->...my properties
Still looking for a simpler way to access it.
Solution 8:[8]
I have had the same problem, but my case was a bit special, because I push my data to view via view()->share($params); and in such cases the solution: $content = $response->getOriginalContent()->getData(); does not give the data out.
and I could not use $response->assertViewHas(...) because my data was objects (models) and I needed to verify object properties (keys and id-s).
So my solution was
$data = $response->original->gatherData();
$this->assertSame($currency->key, $data['currency']->key);
Tested on Laravel 8
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow

