Simular un método en la misma clase que se está probando

3 minutos de lectura

avatar de usuario
James

Quiero simular un método en la misma clase que estoy probando.

ClassA {
   function hardToTest($arg) {
      // difficult to test code
   }

   function underTest() {
      return $this->hardToTest('foo');
   }
}

Estaba pensando que podría usar la reflexión para hacer esto, pero tal vez solo sea una señal de que debería moverme. hardToTest en otro objeto.

  • Estoy usando PhpUnit 5.7 y necesitaba usar createPartialMock y especifique qué métodos deben simularse.

    – Ryan

    14 de julio de 2017 a las 18:11

  • Acepto que tener que simular un método en la misma clase que se está probando es un olor a código, y que el método debe moverse a otra clase.

    –Leo Galleguillos

    16 de enero de 2018 a las 22:16

avatar de usuario
david harkness

Esta prueba tendrá éxito si underTest() pasa 'foo' a hardToTest(). Esto se conoce como simulacro parcial en la documentación de PHPUnit porque solo se está burlando de algunos de los métodos.

ClassATest {
    function testUnderTest() {
        $mock = $this->getMock('ClassA', ['hardToTest']);
        $mock->expects($this->once())
             ->method('hardToTest')
             ->with('foo');
        $mock->underTest();
    }
}

Estoy de acuerdo con sus instintos de que esta necesidad puede ser un olor a código que le dice que esta clase está haciendo demasiado.

Unidad PHP 5.4+

Ya que getMock() quedó en desuso en 5.4, use getMockBuilder() en cambio:.

$mock = $this->getMockBuilder('ClassA')
             ->setMethods(['hardToTest'])    // onlyMethods in 8.4+
             ->ge‌​tMock();

  • en realidad debería ser $mock = $this->getMock('ClassA', [ 'hardToTest' ]); segundo parámetro de getMock se espera que sea una matriz de nombres de métodos.

    – Stefano Torresi

    11 de julio de 2014 a las 9:38

  • En algunos casos, deberá realizar una simulación parcial, por ejemplo, si uno de los métodos de clase realiza una solicitud HTTP. Sería bueno burlarse de ese método y devolver un código auxiliar para la solicitud.

    – b01

    28/06/2016 a las 16:00

  • @julestruong $this->getMockBuilder(class)->setMethods(['methodName'])->getMock();

    – jorar91

    16/03/2017 a las 23:35


  • Estoy de acuerdo contigo en que es un olor a código. Siempre que tenga que simular un método de la misma clase, es hora de pensar en moverlo a una clase independiente. Hará que sus pruebas sean mucho más fáciles. sufrí esto.

    – tucq88

    20 de julio de 2017 a las 10:37

  • también puedes usar $this->getMockBuilder('ClassA')->setConstructorArgs([$arg1, $arg2])

    – oceanBT

    21 de agosto de 2019 a las 10:11


Lo que recurrí fue crear una subclase de mi sistema bajo prueba con el método relevante desconectado.

avatar de usuario
tereško

¿Cuál es exactamente la razón por la cual el método es difícil de probar?

Si el método está protegido y realmente desea probarlo, puede ampliar su ClassA y hacer que el hardToTest($arg) público.

La conclusión es que no debe modificar la clase solo porque necesita escribir unittest para ella. Y en general, la private y protected los métodos no deben probarse; solo debe probar la interfaz pública.

  • Necesito probar un método que llame a otro método en LA MISMA CLASE. Me gustaría poder simular la funcionalidad de ese método en tiempo de ejecución. Mover el método a otra clase no es mi opción preferida.

    – James

    26/04/2011 a las 20:00

  • sí, eso es bastante parecido a la idea… crear una subclase del sistema bajo prueba y eliminar los métodos relevantes que no quiero probar. gracias por la ayuda

    – James

    26 de abril de 2011 a las 20:03

  • PlusOne para ti mencionando La línea de fondo

    – Phil

    19 de octubre de 2017 a las 8:57

  • “La conclusión es que no debe modificar la clase solo porque necesita escribir unittest para ella”. Una clase (o código) que no puede someterse a pruebas unitarias es una clase (o código) mal escrita.

    – usuario3790897

    9 de enero de 2018 a las 10:45

¿Ha sido útil esta solución?