从路由返回了无效 JSON。也许抛出了异常?
Invalid JSON was returned from the route. Perhaps an exception was thrown?
我一直在努力将 JWT authentication 添加到我的 Lumen API。请记住,我是 Lumen、API 设计和 TDD 的新手。在添加身份验证之前,所有测试都已通过。老实说,除了我 运行 phpunit.难以理解的是,当我 运行 在邮递员中进行相同的测试时,我没有任何问题,但是当我在 phpunit 中转储响应时,我得到 NULL
。也许一双新眼睛可以帮助我?
我已将 jwt.auth 中间件添加到我的受限路由中:
routes.php
// all other code omitted
$app->group([
'prefix' => $version . '/authors',
'middleware' => 'jwt.auth',
'namespace' => 'App\Http\Controllers',
], function ($app) {
$app->get('/{id:[\d]+}', ['as' => 'authors.show', 'uses' => 'AuthorsController@show']);
});
我的部分控制器如下:
AuthorsController.php
class AuthorsController extends Controller
{
// all other code omitted
public function show($id)
{
return $this->item(Author::findOrFail($id), new AuthorTransformer());
}
}
我的模型如下
Author.php
class Author extends Model
{
/**
* The attributes that are mass assignable
*
* @var array
*/
protected $fillable = ['name', 'biography', 'gender'];
public function books()
{
return $this->hasMany(Book::class);
}
}
而我的Transformer如下:
AuthorTransformer.php
class AuthorTransformer extends TransformerAbstract
{
protected $availableIncludes = [
'books',
];
public function includeBooks(Author $author)
{
return $this->collection($author->books, new BookTransformer());
}
/**
* Transform an author model
*
* @param Author $author
* @return array
*/
public function transform(Author $author)
{
return [
'id' => $author->id,
'name' => $author->name,
'gender' => $author->gender,
'biography' => $author->biography,
'created' => $author->created_at->toIso8601String(),
'updated' => $author->created_at->toIso8601String(),
];
}
}
而我的测试如下:
TestCase.php
class TestCase extends Laravel\Lumen\Testing\TestCase
{
// all other code omitted
/**
* Convenience method for creating a user
*
* @return $user
*/
protected function userFactory()
{
$user = factory(\App\User::class, 1)->create(['password' => app('hash')->make('supersecret')]);
return $user;
}
/**
* Convenience method for getting jwt and authenticating
*
* @return $body
*/
protected function jwtAuthTest($method, $url, $body = [])
{
$user = $this->userFactory();
$token = JWTAuth::fromUser($user);
JWTAuth::setToken($token);
$headers = array(
"Accept" => "application/json",
"Authorization" => "Bearer " . $token,
);
switch ($method) {
case 'get':
$this->get($url, $body, $headers);
break;
case 'post':
$this->post($url, $body, $headers);
break;
case 'put':
$this->put($url, $body, $headers);
break;
case 'patch':
$this->patch($url, $body, $headers);
break;
case 'delete':
$this->delete($url, $body, $headers);
break;
}
$data = json_decode($this->response->getContent(), true);
return $data;
}
}
AuthorsControllerTest.php
class AuthorsControllerTest extends TestCase
{
// all other code omitted
/** @test **/
public function show_should_fail_on_an_invalid_author()
{
$body = $this->jwtAuthTest('get', '/v1/authors/1234');
// this works fine...
$this->seeStatusCode(Response::HTTP_NOT_FOUND);
// NULL??
var_dump($body);
}
}
我的回复应该是:
{
"error": {
"message": "Not Found",
"status": 404
}
}
但是我得到 NULL
当我在 Postman 中使用有效令牌测试相同的路由时,我得到了我在测试中所期望的结果:
{
"error": {
"message": "Not Found",
"status": 404
}
}
我的路由突然在 phpunit 测试中返回 null。我似乎无法弄清楚为什么?
我的处理程序如下:
// all other code omitted
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
ValidationException::class,
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $e
* @return void
*/
public function report(Exception $e)
{
parent::report($e);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
if ($request->wantsJson()) {
$response = [
'message' => (string) $e->getMessage(),
'status' => 400,
];
if ($e instanceof HttpException) {
$response['message'] = Response::$statusTexts[$e->getStatusCode()];
$response['status'] = $e->getStatusCode();
} else if ($e instanceof ModelNotFoundException) {
$response['message'] = Response::$statusTexts[Response::HTTP_NOT_FOUND];
$response['status'] = Response::HTTP_NOT_FOUND;
}
if ($this->isDebugMode()) {
$response['debug'] = [
'exception' => get_class($e),
'trace' => $e->getTrace(),
];
}
return response()->json(['error' => $response], $response['status']);
}
return parent::render($request, $e);
}
}
当我的测试失败时,我得到:
There was 1 failure:
1) Tests\App\Http\Controllers\AuthorsControllerTest::show_should_fail_on_an_invalid_author
Invalid JSON was returned from the route. Perhaps an exception was thrown?
如果您还需要什么,请告诉我,谢谢。
问题在于 TestCase.php
存在简单的命名冲突和 get() 方法的无效使用:
TestCase.php
/**
* Convenience method for getting jwt and authenticating
*
* @return $body
*/
protected function jwtAuthTest($method, $url, $body = [])
{
$user = $this->userFactory();
$token = JWTAuth::fromUser($user);
JWTAuth::setToken($token);
$headers = array(
"Accept" => "application/json",
"Authorization" => "Bearer " . $token,
);
switch ($method) {
case 'get':
// [FIX] removed $body from get request as this was overwriting my headers
// and causing my handler to return plain text instead of JSON
$this->get($url, $headers);
break;
case 'post':
$this->post($url, $body, $headers);
break;
case 'put':
$this->put($url, $body, $headers);
break;
case 'patch':
$this->patch($url, $body, $headers);
break;
case 'delete':
$this->delete($url, $body, $headers);
break;
}
// [FIX] changed $body= json_decode($this->response->getContent(), true);
$data = json_decode($this->response->getContent(), true);
return $data;
}
我一直在努力将 JWT authentication 添加到我的 Lumen API。请记住,我是 Lumen、API 设计和 TDD 的新手。在添加身份验证之前,所有测试都已通过。老实说,除了我 运行 phpunit.难以理解的是,当我 运行 在邮递员中进行相同的测试时,我没有任何问题,但是当我在 phpunit 中转储响应时,我得到 NULL
。也许一双新眼睛可以帮助我?
我已将 jwt.auth 中间件添加到我的受限路由中:
routes.php
// all other code omitted
$app->group([
'prefix' => $version . '/authors',
'middleware' => 'jwt.auth',
'namespace' => 'App\Http\Controllers',
], function ($app) {
$app->get('/{id:[\d]+}', ['as' => 'authors.show', 'uses' => 'AuthorsController@show']);
});
我的部分控制器如下:
AuthorsController.php
class AuthorsController extends Controller
{
// all other code omitted
public function show($id)
{
return $this->item(Author::findOrFail($id), new AuthorTransformer());
}
}
我的模型如下
Author.php
class Author extends Model
{
/**
* The attributes that are mass assignable
*
* @var array
*/
protected $fillable = ['name', 'biography', 'gender'];
public function books()
{
return $this->hasMany(Book::class);
}
}
而我的Transformer如下:
AuthorTransformer.php
class AuthorTransformer extends TransformerAbstract
{
protected $availableIncludes = [
'books',
];
public function includeBooks(Author $author)
{
return $this->collection($author->books, new BookTransformer());
}
/**
* Transform an author model
*
* @param Author $author
* @return array
*/
public function transform(Author $author)
{
return [
'id' => $author->id,
'name' => $author->name,
'gender' => $author->gender,
'biography' => $author->biography,
'created' => $author->created_at->toIso8601String(),
'updated' => $author->created_at->toIso8601String(),
];
}
}
而我的测试如下:
TestCase.php
class TestCase extends Laravel\Lumen\Testing\TestCase
{
// all other code omitted
/**
* Convenience method for creating a user
*
* @return $user
*/
protected function userFactory()
{
$user = factory(\App\User::class, 1)->create(['password' => app('hash')->make('supersecret')]);
return $user;
}
/**
* Convenience method for getting jwt and authenticating
*
* @return $body
*/
protected function jwtAuthTest($method, $url, $body = [])
{
$user = $this->userFactory();
$token = JWTAuth::fromUser($user);
JWTAuth::setToken($token);
$headers = array(
"Accept" => "application/json",
"Authorization" => "Bearer " . $token,
);
switch ($method) {
case 'get':
$this->get($url, $body, $headers);
break;
case 'post':
$this->post($url, $body, $headers);
break;
case 'put':
$this->put($url, $body, $headers);
break;
case 'patch':
$this->patch($url, $body, $headers);
break;
case 'delete':
$this->delete($url, $body, $headers);
break;
}
$data = json_decode($this->response->getContent(), true);
return $data;
}
}
AuthorsControllerTest.php
class AuthorsControllerTest extends TestCase
{
// all other code omitted
/** @test **/
public function show_should_fail_on_an_invalid_author()
{
$body = $this->jwtAuthTest('get', '/v1/authors/1234');
// this works fine...
$this->seeStatusCode(Response::HTTP_NOT_FOUND);
// NULL??
var_dump($body);
}
}
我的回复应该是:
{
"error": {
"message": "Not Found",
"status": 404
}
}
但是我得到 NULL
当我在 Postman 中使用有效令牌测试相同的路由时,我得到了我在测试中所期望的结果:
{
"error": {
"message": "Not Found",
"status": 404
}
}
我的路由突然在 phpunit 测试中返回 null。我似乎无法弄清楚为什么?
我的处理程序如下:
// all other code omitted
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
ValidationException::class,
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $e
* @return void
*/
public function report(Exception $e)
{
parent::report($e);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
if ($request->wantsJson()) {
$response = [
'message' => (string) $e->getMessage(),
'status' => 400,
];
if ($e instanceof HttpException) {
$response['message'] = Response::$statusTexts[$e->getStatusCode()];
$response['status'] = $e->getStatusCode();
} else if ($e instanceof ModelNotFoundException) {
$response['message'] = Response::$statusTexts[Response::HTTP_NOT_FOUND];
$response['status'] = Response::HTTP_NOT_FOUND;
}
if ($this->isDebugMode()) {
$response['debug'] = [
'exception' => get_class($e),
'trace' => $e->getTrace(),
];
}
return response()->json(['error' => $response], $response['status']);
}
return parent::render($request, $e);
}
}
当我的测试失败时,我得到:
There was 1 failure:
1) Tests\App\Http\Controllers\AuthorsControllerTest::show_should_fail_on_an_invalid_author
Invalid JSON was returned from the route. Perhaps an exception was thrown?
如果您还需要什么,请告诉我,谢谢。
问题在于 TestCase.php
存在简单的命名冲突和 get() 方法的无效使用:
TestCase.php
/**
* Convenience method for getting jwt and authenticating
*
* @return $body
*/
protected function jwtAuthTest($method, $url, $body = [])
{
$user = $this->userFactory();
$token = JWTAuth::fromUser($user);
JWTAuth::setToken($token);
$headers = array(
"Accept" => "application/json",
"Authorization" => "Bearer " . $token,
);
switch ($method) {
case 'get':
// [FIX] removed $body from get request as this was overwriting my headers
// and causing my handler to return plain text instead of JSON
$this->get($url, $headers);
break;
case 'post':
$this->post($url, $body, $headers);
break;
case 'put':
$this->put($url, $body, $headers);
break;
case 'patch':
$this->patch($url, $body, $headers);
break;
case 'delete':
$this->delete($url, $body, $headers);
break;
}
// [FIX] changed $body= json_decode($this->response->getContent(), true);
$data = json_decode($this->response->getContent(), true);
return $data;
}