从路由返回了无效的 JSON。也许抛出了异常?
Posted
技术标签:
【中文标题】从路由返回了无效的 JSON。也许抛出了异常?【英文标题】:Invalid JSON was returned from the route. Perhaps an exception was thrown? 【发布时间】:2017-03-18 17:46:38 【问题描述】:我一直在努力将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());
我的模型如下
作者.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?
如果您需要其他任何东西,请告诉我,并提前感谢您。
源码:https://github.com/studio174/gscp
【问题讨论】:
【参考方案1】:问题在于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;
【讨论】:
以上是关于从路由返回了无效的 JSON。也许抛出了异常?的主要内容,如果未能解决你的问题,请参考以下文章
在 JSON.Net 中处理不存在的 JSON 令牌如何返回默认值而不是抛出异常
抛出异常或返回 null 是不是更适合 Java? [复制]