如何在 Laravel 中基于 application/json 标头加载路由
I'm using the application/json
header to control how my controller acts when a request is received. I need for the POST in my unit test to include an application/json
header.
I've tried:
public function testStore()
{
$this->validator
->shouldReceive('validate')
->once()
->with($this->attributes)
->andReturn(true);
$this->repository
->shouldReceive('create')
->once()
->with($this->attributes)
->andReturn($this->entity);
$this->controller
->shouldReceive('creationSucceeded')
->once()
->with($this->entity);
$this->client->request('POST', 'shared/users', [], [], [
'HTTP_CONTENT_TYPE' => 'application/json'
], json_encode($this->attributes));
$this->assertResponseStatus(201);
}
And it the Request::isJson()
in my controller continues to return false.
I also tried using 'CONTENT_TYPE' => 'application/json'
instead of the HTTP_CONTENT_TYPE
above.
In my case, I was using Content-Type
to determine which controllers to load. This didn't work for me, because routes are loaded into memory when TestCase->createApplication()
is run. This means my headers had no effect.
I ended up making a RouteInflector
that allows me to force my tests to use the Api routes.
class ApiTestCase extends TestCase
{
/**
* @inheritDoc
*/
public static function setUpBeforeClass()
{
/**
* Routes are loaded into memory before tests are run.
* Because of this, we can't have routing logic based on
* heads. Using the RouteInflector we can override
* header to createApplication() and must use a constant
* to force the RouteInflector to use Api controllers.
*/
RouteInflector::isJson(true);
}
public function setUp()
{
parent::setUp();
//Lets do this right
$this->client->setServerParameter('HTTP_CONTENT_TYPE', 'application/json');
$this->client->setServerParameter('HTTP_ACCEPT', 'application/json');
}
}
Inflector:
class RouteInflector
{
/** @var bool */
protected static $isJson = false;
/**
* Review the request details and determine which controller
* subpackage should be used.
* We could also check the request source to help determine the
* package.
*
* Defaults to Web.
*
* @return string
*/
public function getControllerSubpackage()
{
if (self::isJson() || Request::isJson()) {
return 'Api';
}
return 'Web';
}
/**
* Used by tests to tell routing that the current request
* is a json request.
*
* @see TestsApiTestCase
*
* @param bool|null $isJson
*
* @return bool Only provided if parameter is null
*/
public static function isJson($isJson = null)
{
if (is_null($isJson)) {
return self::$isJson;
} else {
self::$isJson = $isJson;
}
}
}
相关文章