If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
The nice API Problem JSON format always has a type
key, so let's at least start
looking for that in the response. Use $this->asserter()->assertResponsePropertyEquals()
and pass it the $response
and type
as the key. For the value - how about
invalid_body_format
. That's our second special error "type" - the first was
validation_error
.
... lines 1 - 5 | |
class ProgrammerControllerTest extends ApiTestCase | |
{ | |
... lines 8 - 147 | |
public function testInvalidJson() | |
{ | |
... lines 150 - 162 | |
$this->assertEquals(400, $response->getStatusCode()); | |
$this->asserter()->assertResponsePropertyEquals($response, 'type', 'invalid_body_format'); | |
} | |
... line 166 | |
} |
This should get our test to fail again:
./bin/phpunit -c app --filter testInvalidJson
Gooood - we're still returning the exception HTML.
Let's fix this just like we did for validation errors: by creating an ApiProblem
object. First, we need a new type
constant. Create a second constant called
TYPE_INVALID_REQUEST_BODY_FORMAT
and set that to the string from our test: invalid_body_format
.
Setup a title for this too: how about "Invalid JSON format sent". And I better fix
my syntax error:
... lines 1 - 7 | |
class ApiProblem | |
{ | |
const TYPE_VALIDATION_ERROR = 'validation_error'; | |
const TYPE_INVALID_REQUEST_BODY_FORMAT = 'invalid_body_format'; | |
private static $titles = array( | |
self::TYPE_VALIDATION_ERROR => 'There was a validation error', | |
self::TYPE_INVALID_REQUEST_BODY_FORMAT => 'Invalid JSON format sent', | |
); | |
... lines 17 - 58 | |
} |
Back in ProgrammerController
, we can get to work: $apiProblem = new ApiProblem()
.
Pass it the 400 status code and the type: ApiProblem::TYPE_INVALID_REQUEST_BODY_FORMAT
:
... lines 1 - 17 | |
class ProgrammerController extends BaseController | |
{ | |
... lines 20 - 141 | |
private function processForm(Request $request, FormInterface $form) | |
{ | |
$data = json_decode($request->getContent(), true); | |
if ($data === null) { | |
$apiProblem = new ApiProblem(400, ApiProblem::TYPE_INVALID_REQUEST_BODY_FORMAT); | |
... lines 147 - 148 | |
} | |
... lines 150 - 152 | |
} | |
... lines 154 - 187 | |
} |
Gosh, everything is going really well! And now we're stuck. For validation, we took
the ApiProblem
, turned it into a Response and returned it. But inside processForm()
,
we're big trouble: the return value of this method isn't being used. We can
only throw an exception to stop the flow. And while we can control the status
code of an exception, the response body that an HttpException
generates is still
an HTML error page.
"Houston: no signs of life"
Start the conversation!
// composer.json
{
"require": {
"php": ">=5.3.3",
"symfony/symfony": "2.6.*", // v2.6.11
"doctrine/orm": "~2.2,>=2.2.3,<2.5", // v2.4.7
"doctrine/dbal": "<2.5", // v2.4.4
"doctrine/doctrine-bundle": "~1.2", // v1.4.0
"twig/extensions": "~1.0", // v1.2.0
"symfony/assetic-bundle": "~2.3", // v2.6.1
"symfony/swiftmailer-bundle": "~2.3", // v2.3.8
"symfony/monolog-bundle": "~2.4", // v2.7.1
"sensio/distribution-bundle": "~3.0,>=3.0.12", // v3.0.21
"sensio/framework-extra-bundle": "~3.0,>=3.0.2", // v3.0.7
"incenteev/composer-parameter-handler": "~2.0", // v2.1.0
"hautelook/alice-bundle": "0.2.*", // 0.2
"jms/serializer-bundle": "0.13.*" // 0.13.0
},
"require-dev": {
"sensio/generator-bundle": "~2.3", // v2.5.3
"behat/behat": "~3.0", // v3.0.15
"behat/mink-extension": "~2.0.1", // v2.0.1
"behat/mink-goutte-driver": "~1.1.0", // v1.1.0
"behat/mink-selenium2-driver": "~1.2.0", // v1.2.0
"phpunit/phpunit": "~4.6.0" // 4.6.4
}
}