How to simulate xmlHttpRequests in a laravel testcase?

怎甘沉沦 提交于 2019-12-21 04:49:13

问题


Updates see below

My controllers distinguish between ajax and other requests (using Request::ajax() as a condition). That works quite fine but I wonder if there is a way of unit testing the controllers handling the the requests. How should a test look like? Something like this probably but it doesn't work ...

<?php

    class UsersControllerTest extends TestCase
        {


            public function testShowUser()
            {
                $userId = 1;
                $response = $this->call('GET', '/users/2/routes', array(), array(), array(
                    'HTTP_CUSTOM' => array(
                        'X-Requested-With' => 'XMLHttpRequest'
                    )
                ));


            }
        }

Update

I kind of found a solution. Maybe. Since I am not interested in testing the proper functionality of the Request class (very likely all native classes provided by Laravel, Symfony, etc. are enough unit tested already) best way might be to mock its ajax method. Like this:

        public function testShowUser()
        {

            $mocked = Request::shouldReceive('ajax')
                ->once()
                ->andReturn(true);
            $controller = new UsersCustomRoutesController;
            $controller->show(2,2);
        }

Because the real Request class and not its mocked substitute is used when using the call method of the Testcase class I had to instantiate the method which is called when the specified route is entered by hand. But I think that is okay because I just want to control that the expressions inside the Request::ajax() condition work as expected with this test.


回答1:


You need to prefix the actual header with HTTP_, no need to use HTTP_CUSTOM:

$server = array('HTTP_X-Requested-With' => 'XMLHttpRequest');
$this->call('get', '/ajax-route', array(), array(), $server);

Alternative syntax which looks a bit better IMO:

$this->client->setServerParameter('HTTP_X-Requested-With', 'XMLHttpRequest');
$this->call('get', '/ajax-route');

Here are some similar code examples for JSON headers (Request::isJson() and Request::wantsJson()):

$this->client->setServerParameter('HTTP_CONTENT_TYPE', 'application/json');
$this->call('get', '/is-json');

$this->client->setServerParameter('HTTP_ACCEPT', 'application/json');
$this->call('get', '/wants-json');

Here's a useful helper method you can put in your TestCase:

protected function prepareAjaxJsonRequest()
{
    $this->client->setServerParameter('HTTP_X-Requested-With', 'XMLHttpRequest');
    $this->client->setServerParameter('HTTP_CONTENT_TYPE', 'application/json');
    $this->client->setServerParameter('HTTP_ACCEPT', 'application/json');
}



回答2:


Here's the solution for Laravel 5.2.

$this->json('get', '/users/2/routes');

It's that simple.


Intenally, json method applies following headers:

'CONTENT_LENGTH' => mb_strlen($content, '8bit'),
'CONTENT_TYPE'   => 'application/json',
'Accept'         => 'application/json',



回答3:


In Laravel 5:

$this->get('/users/2/routes', ['HTTP_X-Requested-With' => 'XMLHttpRequest']);

Then you can chain the normal assertions:

$this->get('/users/2/routes', ['HTTP_X-Requested-With' => 'XMLHttpRequest'])
    ->seeJsonStructure([
        '*' => ['id', 'name'],
    ]);



回答4:


$server = array('HTTP_X-Requested-With' => 'XMLHttpRequest');
$request = new \Illuminate\Http\Request($query = array(),$request = array(), $attributes = array(), $cookies = array(), $files = array(), $server , $content = null);   



回答5:


Laravel 5.X

As an addition to already existing answers, and for clarity purpose you can add those helper methods to your TestCase

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    // ...

    /**
     * Make ajax POST request
     *
     * @param  string $uri
     * @param  array  $data
     * @return \Illuminate\Foundation\Testing\TestResponse
     */
    public function ajaxPost($uri, array $data = [])
    {
        return $this->post($uri, $data, ['HTTP_X-Requested-With' => 'XMLHttpRequest']);
    }


    /**
     * Make ajax GET request
     *
     * @param  string $uri
     * @return \Illuminate\Foundation\Testing\TestResponse
     */
    public function ajaxGet($uri)
    {
        return $this->get($uri, ['HTTP_X-Requested-With' => 'XMLHttpRequest']);
    }
}

Usage

<?php

class ExampleTest extends TestCase
{
    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->ajaxPost('/user', ['name' => 'Sally']);

        $response
            ->assertStatus(201)
            ->assertJson([
                'created' => true,
            ]);
    }
}


来源:https://stackoverflow.com/questions/20093897/how-to-simulate-xmlhttprequests-in-a-laravel-testcase

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!