vendredi 4 mai 2018

Using a "fake controller" to test response with Symfony and Behat

I'm working with FOSRestBundle and Symfony4 to create a REST API, and I overwrote the default view to always return an object as following:

{
    code: 200,
    message: 'Success!',
    data: {}
}

For exceptions, the code and the message will change to 404, 401, 403, and so on.

To achieve that, I created my own view classes that extends \FOS\RestBundle\View\View, so now I can return my view object in any controller action, and since I have the view_response_listener enabled on fos_rest.yaml, the FOSRestBundle will listen to my View return and transform it into a Response. For example:

<?php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use App\View\Ok;
use App\Entity\User;

/**
 * @Rest\Route("/user")
 */
class UserController extends FOSRestController
{
    /**
     * @Rest\Get("/")
     */
    public function getUserAction(Request $request)
    {
        $users = $this->getDoctrine()
            ->getRepository(User::class)->findAll();
        return new Ok(['users' => $users]);
    }
}

So in this example, the API output should be:

{
    code: 200,
    message: 'Success!',
    data: { users: [ /* Users here... */ ] }
}

Ok, so far so good. The problem is that I need to test if given a request sent to a fake controller, that has actions to simulate success and exception return, I get the properly object, using my View.

I'm using Behat, so I'm going to write this example scenario:

Scenario: "Ok" response test
    When send a request to "/response-test/ok"
    Then the response status code should be 200
    And the response should to be JSON
    And the response should to be equal
    """
        {
           code: 200,
           message: 'Success!',
           data: {}
        }
    """

Scenario: "Not found" response test
    When send a request to "/response-test/not-found"
    Then the response status code should be 404
    And the response should to be JSON
    And the response should to be equal
    """
        {
           code: 404,
           message: 'Not found!',
           data: {}
        }
    """

My question is: is there a way to define a fake controller, as following, that act exactly like a real controller (including the annotations and REST behavior), but that lives in my test suite, and servers only to my tests? Something like:

<?php

namespace App\Tests;

use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Controller\Annotations as Rest;
use App\View\Ok;
use App\View\NotFound;

/**
 * @Rest\Get("/response-test")
 */
class TestController extends FOSRestController
{

    /**
     * @Rest\Get("/ok")
     */
    public function okAction(Request $request)
    {
        return new Ok();
    }

    /**
     * @Rest\Get("/not-found")
     */
    public function notFoundAction(Request $request)
    {
        return new NotFound();
    }

}

I can't make this controller work because when I define it outside the folder src/Controller, Symfony doesn't recognize it, and I don't want to define this controller together the application's one.

What is the best way to make this test?

Aucun commentaire:

Enregistrer un commentaire