8

Gần đây tôi cần kiểm tra một phần của Slim sử dụng các hàm PHP tích hợp  header() và  headers_sent(). Để làm điều này, tôi đã tận dụng các quy tắc phân giải không gian tên của PHP nơi nó sẽ tìm thấy một hàm trong cùng một không gian tên trước khi tìm một hàm có cùng tên trong không gian tên toàn cục. Ý tưởng về cách thực hiện điều này được đưa ra nhờ sự giúp đỡ của Matthew Weier O'Phinney , nơi phương pháp này được sử dụng để thử nghiệm tương tự trong Zend-Diactoros .

Đây là phần có liên quan của mã tôi muốn kiểm tra:

namespace Slim;

// use statements...

class App
{
    // ... 

    public function respond(ResponseInterface $response)
    {
        // Send response
        if (!headers_sent()) {
            // Headers
            foreach ($response->getHeaders() as $name => $values) {
                $first = stripos($name, 'Set-Cookie') === 0 ? false : true;
                foreach ($values as $value) {
                    header(sprintf('%s: %s', $name, $value), $first);
                    $first = false;
                }
            }
        }

        // method continues
    }

     // ... 
}


Đây là bài kiểm tra có liên quan (đơn giản hóa):

namespace Slim\Tests;

// use statements...

class AppTest extends PHPUnit_Framework_TestCase
{
    // ... 

    public function testResponseReplacesPreviouslySetHeaders()
    {
        $app = new App();

        $response = new Response();
        $response = $response->withHeader('X-Foo', 'baz1')
                ->withAddedHeader('X-Foo', 'baz2');

        $app->respond($response);

        $expectedStack = [
            ['header' => 'X-Foo: baz1', 'replace' => true, 'status_code' => null],
            ['header' => 'X-Foo: baz2', 'replace' => false, 'status_code' => null],
        ];

        $this->assertSame($expectedStack, HeaderStackTestAsset::$headers);
    }

    // ... 
}

Mã này thiết lập một đối tượng Phản hồi với hai tiêu đề X-Foo, sau đó nó gọi  respond() và kiểm tra rằng có hai lệnh gọi  header() với tham số thay thế được đặt thành đúng chỉ cho đầu tiên.

Để làm việc này, chúng ta cần ghi đè lên PHP  header() và thay thế nó bằng chính chúng ta lưu trữ các tham số thành một mảng trong  HeaderStackTestAsset lớp.

Điều này được thực hiện bằng cách tạo HeaderStackTestAsset lớp riêng của chúng ta  cùng với  headers_sent() và các  header() hàm được gọi thay vì của PHP:

// test/Assets/HeaderFunctions.php

namespace Slim\Tests\Assets {

    class HeaderStackTestAsset
    {
        public static $headers = [];
    }
}

namespace Slim {

    function headers_sent()
    {
        return false;
    }

    function header($header, $replace = true, $statusCode = null)
    {
        \Slim\Tests\Assets\HeaderStackTestAsset::$headers[] = [
            'header' => $header,
            'replace' => $replace,
            'status_code' => $statusCode,
        ];
    }
}

Các  HeaderStackTestAsset lớp học là tầm thường và tồn tại hoàn toàn như một người giữ cho chúng tôi  $headers mảng.

Sau đó, chúng tôi xác định  headers_sent() hàm của mình để luôn trả về false và sau đó  header() được thiết lập để lưu trữ các tham số hàm cho  HeaderStackTestAsset::$headers mảng.

Điều quan trọng ở đây là  headers_sent() và các  header() chức năng nằm trong không gian tên Slim . Vì Ứng dụng cũng nằm trong cùng một không gian tên khi  header() được gọi bên trong respond(); phiên bản của chúng tôi được gọi và vì vậy chúng tôi có thể đảm bảo rằng Slim thực hiện đúng với $replace   tham số.

Đây là một mẹo rất hữu ích khi bạn cần nó và hoạt động cho bất kỳ hàm PHP nào được gọi trong không gian tên toàn cầu (miễn là tệp không nhập rõ ràng bằng cách sử dụng).

|