Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

phpunit error "must be a array or ArrayAccess" #18280

Closed
nisevi opened this issue Mar 9, 2017 · 14 comments
Closed

phpunit error "must be a array or ArrayAccess" #18280

nisevi opened this issue Mar 9, 2017 · 14 comments

Comments

@nisevi
Copy link

nisevi commented Mar 9, 2017

  • Laravel Version: 5.3.30
  • PHP Version: 7.1.0
  • Database Driver & Version: pgsql
$ phpunit --version
PHPUnit 5.7.15 by Sebastian Bergmann and contributors.

Description:

When running tests with phpunit I get:

$ phpunit --filter RoleControllerTest
PHPUnit 5.7.15 by Sebastian Bergmann and contributors.

E...                                                                4 / 4 (100%)

Time: 1.64 seconds, Memory: 24.00MB

There was 1 error:

1) RoleControllerTest::testMethodAll
PHPUnit_Framework_Exception: Argument #2 (No Value) of PHPUnit_Framework_Assert::assertArrayHasKey() must be a array or ArrayAccess

/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:369
/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:363
/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:367
/home/nisevi/documents/recom-electronics/keepclear-backend/tests/api/RoleControllerTest.php:19

Steps To Reproduce:

I'm trying to validate this structure:

 13     public function testMethodAll()                                                                                                                                                                            
 14     {                                                                                                                                                                                                          
 15         factory(Role::class, 'superadmin')->create();                                                                                                                                                          
 16         $this->get('api/v1/roles')                                                                                                                                                                             
 17             ->seeJsonStructure(                                                                                                                                                                                
 18                 [                                                                                                                                                                                              
 19                     'total',                                                                                                                                                                                   
 20                     'per_page',                                                                                                                                                                                
 21                     'current_page',                                                                                                                                                                            
 22                     'last_page',                                                                                                                                                                               
 23                     'next_page_url',                                                                                                                                                                           
 24                     'prev_page_url',                                                                                                                                                                           
 25                     'from',                                                                                                                                                                                    
 26                     'to',                                                                                                                                                                                      
 27                     'data' => [                                                                                                                                                                                
 28                         '*' => [                                                                                                                                                                               
 29                             'id',                                                                                                                                                                              
 30                             'name',                                                                                                                                                                            
 31                             'description',                                                                                                                                                                     
 32                             'created_at',                                                                                                                                                                      
 33                             'updated_at'                                                                                                                                                                       
 34                         ],                                                                                                                                                                                     
 35                         'limit'                                                                                                                                                                                
 36                     ]                                                                                                                                                                                          
 37                 ]                                                                                                                                                                                              
 38             );                                                                                                                                                                                                 
 39     } 

If I wrongly change (on purpose) one of the expected keys inside "data" I get the expected behavior:

$ phpunit --filter RoleControllerTest
PHPUnit 5.7.15 by Sebastian Bergmann and contributors.

F...                                                                4 / 4 (100%)

Time: 2.39 seconds, Memory: 24.00MB

There was 1 failure:

1) RoleControllerTest::testMethodAll
Failed asserting that an array has the key 'descriptio'.

/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:369
/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:363
/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:367
/home/nisevi/documents/recom-electronics/keepclear-backend/tests/api/RoleControllerTest.php:19

FAILURES!
Tests: 4, Assertions: 22, Failures: 1.

However if everything is ok with the keys, I get:

$ phpunit --filter RoleControllerTest
PHPUnit 5.7.15 by Sebastian Bergmann and contributors.

E...                                                                4 / 4 (100%)

Time: 2.43 seconds, Memory: 24.00MB

There was 1 error:

1) RoleControllerTest::testMethodAll
PHPUnit_Framework_Exception: Argument #2 (No Value) of PHPUnit_Framework_Assert::assertArrayHasKey() must be a array or ArrayAccess

/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:369
/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:363
/home/nisevi/documents/recom-electronics/keepclear-backend/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:367
/home/nisevi/documents/recom-electronics/keepclear-backend/tests/api/RoleControllerTest.php:19

ERRORS!
Tests: 4, Assertions: 24, Errors: 1.

I asked on phpunit repository, here and they suggest to take a look at the code on the Laravel framework here.

Please let me know if you need more info regarding this issue.

@themsaid
Copy link
Member

themsaid commented Mar 9, 2017

Please ask on the forums, we try to keep this repo for bug reporting only.

@themsaid themsaid closed this as completed Mar 9, 2017
@nisevi
Copy link
Author

nisevi commented Mar 9, 2017

@themsaid yeah well, I'm not asking how to use anything, or trying to get help for checking the keys of a hash, I thought it was a bug. I can make an algorithm for checking each key if I want to, but I wanted to use the method that figures in your documentation, thanks anyways.

@themsaid
Copy link
Member

themsaid commented Mar 9, 2017

@nisevi sorry, we're just trying to narrow down the issues in this repo to only include actual framework bugs.

@ghost
Copy link

ghost commented Oct 26, 2017

+1 to this as a bug

@fabianoP
Copy link

Happens to me too. I think is a bug.

@GuidoHendriks
Copy link
Contributor

If it's a bug, at least include complete steps to reproduce. Current steps to reproduce require depend on the codebase of @nisevi, which we don't have.

@nisevi
Copy link
Author

nisevi commented Jan 22, 2018

@GuidoHendriks if I'm not wrong with the specifications I wrote you should be able to reproduce it since you will have to create an app with:

Laravel Version: 5.3.30
PHP Version: 7.1.0
Database Driver & Version: pgsql

and just write some test to try it, right?

@GuidoHendriks
Copy link
Contributor

@nisevi My point exactly. We'd have to create a new app which does the same as yours does. There are some blanks that we'd have to fill in ourselves. We don't see the data that actually is returned by the request while the behaviour depends on it.

If you would create a new project, what steps would you need to take to reproduce this issue? For example, if you can do it with just a route that returns a hardcoded array and a test along with it, that's a lot easier for people trying to reproduce or solve this issue.

@carlosdelros
Copy link

I had the same issue. This should fix this.
laravel/lumen-framework@47777bb

@alexeycrystal
Copy link

alexeycrystal commented Feb 20, 2019

Maybe it will helps to some one, I hope:
I had the same issue when I had a typo in my URI and called to unavailable route (
the original route was like this:
$router->get('/user/{id}', 'UserController@show');
(I missed an id of the user):

    public function testGetUser()
    {
        $this->json('GET', '/api/v1/user')
            ->seeJsonStructure([
                'data' => [
                    'id',
                    'nickname',
...
                ],
                'status',
                'api_version'
            ])->assertResponseStatus(200);
    } ==> PHPUnit\Framework\Exception: Argument #2 (No Value) of PHPUnit\Framework\Assert::assertArrayHasKey() must be a array or ArrayAccess

So when I have set the correct URI and make a call to an existed route: '/api/v1/user/1' - this issue was gone.

@arckdash
Copy link

As above in case someone can use my input.

In my case, it was happening because I was specifying the structure should return an array when it actually was just a simple object.

Using the example from the original question.

public function testMethodAll()                                                                                                                                                                            
{                                                                                                                                                                                                          
   factory(Role::class, 'superadmin')->create();                                                                                                                                                          
   $this->get('api/v1/roles')                                                                                                                                                                             
       ->seeJsonStructure(                                                                                                                                                                                
           [                                                                                                                                                                                              
               'total',                                                                                                                                                                                   
               'per_page',                                                                                                                                                                                
               'current_page',                                                                                                                                                                            
               'last_page',                                                                                                                                                                               
               'next_page_url',                                                                                                                                                                           
               'prev_page_url',                                                                                                                                                                           
               'from',                                                                                                                                                                                    
               'to',                                                                                                                                                                                      
               'data' => [                                                                                                                                                                                
                   '*' => [       // Here it's literally specifying that this part of the response is an array.                                                                                                                                                                              
                       'id',                                                                                                                                                                              
                       'name',                                                                                                                                                                            
                       'description',                                                                                                                                                                     
                       'created_at',                                                                                                                                                                      
                       'updated_at'                                                                                                                                                                       
                   ],                                                                                                                                                                                     
                   'limit'  // I believe this shouldn't be here as it's the key "data"  cannot be an array and an object at the same time, otherwise "limit" should outside of "data", or "data" should have another key as an array to contain all the fields specified underneath it                                                                                                                                                                            
               ]                                                                                                                                                                                          
           ]                                                                                                                                                                                              
       );                                                                                                                                                                                                 
} 

so basically to validate the following json response:

{                                                                                                                                                                                              
    'total': 1000,                                                                                                                                                                                   
    'per_page': 10,                                                                                                                                                                                
    'current_page': 1,                                                                                                                                                                            
    'last_page': 3,                                                                                                                                                                               
    'next_page_url': '...',                                                                                                                                                                           
    'prev_page_url' '...',                                                                                                                                                                           
    'from': 0,                                                                                                                                                                                    
    'to': 10,                                                                                                                                                                                      
    'data': [
      {
        'id': 1,
        'name': 'name 1',
        'description': '',
        'created_at': '2019-04-19 10:23:31',
        'updated_at': null,
      }
    ],
    'limit': 10                                                                                                                                                                                         
}

the json structure definition should look like:

public function testMethodAll()                                                                                                                                                                            
{                                                                                                                                                                                                          
   factory(Role::class, 'superadmin')->create();                                                                                                                                                          
   $this->get('api/v1/roles')                                                                                                                                                                             
       ->seeJsonStructure(                                                                                                                                                                                
           [                                                                                                                                                                                              
               'total',                                                                                                                                                                                   
               'per_page',                                                                                                                                                                                
               'current_page',                                                                                                                                                                            
               'last_page',                                                                                                                                                                               
               'next_page_url',                                                                                                                                                                           
               'prev_page_url',                                                                                                                                                                           
               'from',                                                                                                                                                                                    
               'to',                                                                                                                                                                                      
               'data' => [                                                                                                                                                                                
                   '*' => [                                                                                                                                                                              
                       'id',                                                                                                                                                                              
                       'name',                                                                                                                                                                            
                       'description',                                                                                                                                                                     
                       'created_at',                                                                                                                                                                      
                       'updated_at'                                                                                                                                                                       
                   ],                                                                                                                                                                                     
               ],
               'limit'                                                                                                                                                                                          
           ]                                                                                                                                                                                              
       );                                                                                                                                                                                                 
} 

But if the key "data" is not an array, then the above should be like:

public function testMethodAll()                                                                                                                                                                            
{                                                                                                                                                                                                          
   factory(Role::class, 'superadmin')->create();                                                                                                                                                          
   $this->get('api/v1/roles')                                                                                                                                                                             
       ->seeJsonStructure(                                                                                                                                                                                
           [                                                                                                                                                                                              
               'total',                                                                                                                                                                                   
               'per_page',                                                                                                                                                                                
               'current_page',                                                                                                                                                                            
               'last_page',                                                                                                                                                                               
               'next_page_url',                                                                                                                                                                           
               'prev_page_url',                                                                                                                                                                           
               'from',                                                                                                                                                                                    
               'to',                                                                                                                                                                                      
               'data' => [                                                                                                                                                                                                                                                                                                                                                             
                       'id',                                                                                                                                                                              
                       'name',                                                                                                                                                                            
                       'description',                                                                                                                                                                     
                       'created_at',                                                                                                                                                                      
                       'updated_at'                                                                                                                                                                                                                                                                                                                                                     
               ],
               'limit'                                                                                                                                                                                          
           ]                                                                                                                                                                                              
       );                                                                                                                                                                                                 
} 

Hope this helps to someone.

@khalilst
Copy link
Contributor

khalilst commented May 9, 2019

It happens to me when array of objects with one prop as follows:

'data' => [
    '*' => [
        '_id',
        'title',
        'sku',
        'categories' => [
            '*' => [ 'name' ],
        ]
    ]
]

It raises an error like this:
Argument #2 (No Value) of PHPUnit\Framework\Assert::assertArrayHasKey() must be a array or ArrayAccess

When I add another prop to categories the error converts to failure.

@taylorotwell
It has problem with objects with single prop and definitely it's a bug.

@jonaswebdev
Copy link

This issue still happening on Laravel 8, I'm stuck on it!!!

@szymekjanaczek
Copy link

szymekjanaczek commented Dec 21, 2021

Everything works correctly for GET request:

$this->getJson($this->baseUri())
    ->assertOk()
    ->assertJsonStructure([
        'data' => [
            '*' => ['id', 'key', 'value', 'type', 'description', 'is_encrypted', 'created_at', 'updated_at']
        ]
    ]);

But when I want to make same assertion after patch request:

$this->patch($this->baseUri() . "/$setting->id", $request) // or ->patchJson - they both don't work...
    ->assertOk()
    ->assertJsonStructure([
        'data' => [
            '*' => ['id', 'key', 'value', 'type', 'description', 'is_encrypted', 'created_at', 'updated_at']
        ]
    ]);

It fails: Argument #2 of PHPUnit\Framework\Assert::assertArrayHasKey() must be an array or ArrayAccess.

  • Laravel: 8.58.0
  • PHP: 8.0.13
  • PHP Unit: 9.5.10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants