No mojes lo que no tienes

Aprox. traductor: la regla en sí es bastante antigua, y el ejemplo que se da en el artículo es, en mi opinión, el más simple. Por lo tanto, el artículo es más adecuado para principiantes, las personas con buena experiencia en la redacción de autotests pueden no encontrar nada nuevo para ellos. UPD. Todavía no creo que el autor proponga envolver todas las API del framework con el que está trabajando con su propia capa (bueno, sería extremadamente extraño), sino que se trata de clases de propósito general poco estructuradas / tipadas, como HttpRequest del ejemplo del artículo.





Las aplicaciones web a menudo están diseñadas para manejar solicitudes HTTP. Los objetos se utilizan comúnmente para encapsular los datos de la solicitud. Dependiendo del marco, podríamos tener una interfaz como





interface HttpRequest
{
    public function get(string $name): string;

    // ...
}
      
      



o incluso una clase específica como





class HttpRequest
{
    public function get(string $name): string
    {
        // ...
    }

    // ...
}
      
      



que podemos (y debemos) utilizar para acceder a los datos de la solicitud.





Symfony, por ejemplo, tiene Symfony \ Component \ HttpFoundation \ Request :: get (). Por ejemplo, no nos preocuparemos por el tipo de solicitud HTTP que estamos manejando (GET, POST u otro). En cambio, centrémonos en las API implícitas como HttpRequest :: get () y los problemas que plantean.





, , , get() , . . get():





class SomeController
{
    public function execute(HttpRequest $request): HttpResponse
    {
        $id     = $request->get('id');
        $amount = $request->get('amount');
        $price  = $request->get('price');

        // ...
    }
}
      
      



, action- (: (eng )). , HTTP-.





HttpRequest (stub) mock- SomeController , get() , : 'id', 'amount' 'price'.





, , action- .





SomeController HttpRequest (stub) unit PHPUnit :





$request = $this->createStub(HttpRequest::class);

$request->method('get')
        ->willReturnOnConsecutiveCalls(
              '1',
              '2',
              '3',
          );

$controller = new SomeController;

$controller->execute($request);
      
      



SomeController HttpRequest, mock-, :





$request = $this->createMock(HttpRequest::class);

$request->expects($this->exactly(3))
        ->method('get')
        ->withConsecutive(
            ['id'],
            ['amount'],
            ['price']
        )
        ->willReturnOnConsecutiveCalls(
            '1',
            '2',
            '3',
        );

$controller = new SomeController;

$controller->execute($request);
      
      



, , , ( . ).





, HttpRequest::get() : «id», «amount» , , «price».





SomeController::execute(), HttpRequest::get(), . , . .





, HTTP-, API, , HTTP, get(). , , , : HttpRequest , .





« , » « , ». 2009 « - »:





« , , , , , . , , , , , ».





, , ? :





« [...] , , - , , . [...], - API [...] "





:





interface SomeRequestInterface
{
    public function getId(): string;

    public function getAmount(): string;

    public function getPrice(): string;
}
      
      



, , value-. .





SomeRequestInterface :





$request = $this->createStub(SomeRequestInterface::class);

$request->method('getId')
        ->willReturn(1);

$request->method('getAmount')
        ->willReturn(2);

$request->method('getPrice')
        ->willReturn(3);
      
      



, HTTP- , - HTTP- . . HTTP- . . :





class SomeRequest implements SomeRequestInterface
{
    private HttpRequest $request;

    public function __construct(HttpRequest $request)
    {
        $this->request = $request;
    }

    public function getId(): string
    {
        return $this->request->get('id');
    }

    public function getAmount(): string
    {
        return $this->request->get('amount');
    }

    public function getPrice(): string
    {
        return $this->request->get('price');
    }
}
      
      



:





class SomeController
{
    public function execute(HttpRequest $request)
    {
        return $this->executable->execute(
            new SomeRequest($request)
        )
    }
}
      
      



SomeController , , HTTP .





Por supuesto, tendrá que hacer que su contenedor de solicitud sea específico para cada controlador. ¿Su código necesita encabezados específicos? Crea un método para conseguirlos. ¿Su código necesita un archivo cargado? Crea un método para conseguir exactamente esto.





Una solicitud HTTP completa puede contener encabezados, valores, tal vez archivos cargados, cuerpo POST, etc. Configurar un código auxiliar de prueba o un simulacro para todo esto mientras no posee la interfaz le impide hacer el trabajo. Definir su propia interfaz simplifica enormemente la tarea.








All Articles