¿Cómo puedo probar métodos privados con DUnit?
-
05-07-2019 - |
Pregunta
Tengo una clase en la que estoy haciendo pruebas de unidad con DUnit. Tiene una serie de métodos, algunos métodos públicos y métodos privados.
type
TAuth = class(TDataModule)
private
procedure PrivateMethod;
public
procedure PublicMethod;
end;
Para escribir una prueba de unidad para esta clase, tengo que hacer públicos todos los métodos.
¿Hay alguna forma diferente de declarar los métodos privados para que aún pueda probarlos pero no son públicos?
Solución
No necesitas hacerlos públicos. Protegido hará. Luego, puede subtipo la clase para la prueba de unidad y resaltar los métodos protegidos. Ejemplo:
type
TAuth = class(TDataModule)
protected
procedure MethodIWantToUnitTest;
public
procedure PublicMethod;
end;
Ahora puedes subtitularlo para tu prueba de unidad:
interface
uses
TestFramework, Classes, AuthDM;
type
// Test methods for class TAuthDM
TestAuthDM = class(TTestCase)
// stuff
end;
TAuthDMTester = class(TAuthDM)
public
procedure MethodIWantToUnitTestMadePublic;
end;
implementation
procedure TAuthDMTester.MethodIWantToUnitTestMadePublic;
begin
MethodIWantToUnitTest;
end;
Sin embargo, si los métodos que desea realizar la prueba unitaria están haciendo las cosas tan íntimamente con el módulo de datos que no es seguro tenerlos a excepción de privados, entonces debería considerar refactorizar los métodos para separar el código que necesita. para ser probado en la unidad y el código que accede a las entrañas del módulo de datos.
Otros consejos
Es un poco intrincado, pero creo que este es el enfoque más simple y claro. Utilice esta directiva de compilación condicional:
{$IfNDef TEST}
private
{$EndIf}
Su proyecto de prueba de unidad debe definir PRUEBA en proyecto ? conditional define
. Sin una especificación de visibilidad, se publican.
Cuidado: si la visibilidad privada no es la primera en la declaración de clase, obtendrá la definición anterior. Una forma más segura, pero más detallada y menos clara, sería:
private
{$IfDef TEST}
public
{$EndIf}
Esto tiene muchas ventajas sobre la subclasificación u otros enfoques:
- Sin complejidad adicional: no hay clases adicionales en su código.
- Nadie puede "equivocadamente" Subclase y anule su clase: usted preserva su arquitectura.
- Cuando dices que un método está protegido, de alguna manera esperas que se invalide. Usted está diciendo esto para quién está leyendo su código. Un método protegido que no debería ser anulado confundirá a sus lectores de código, rompiendo mi primer principio de programación: " el código debe estar escrito para que lo lean otros seres humanos. & Quot;
- DUnit está en su propia unidad, no incluida en todas partes.
- No tocas el RTTI desordenado.
Creo que es una solución más clara y mejor que la respuesta seleccionada.
Cuando uso esto, también configuro el proyecto de prueba para colocar los objetos de compilación en un directorio diferente del proyecto principal. Esto evita que los binarios con la directiva TEST se mezclen con el otro código.
Recomiendo el " XUnit Test Patterns " libro de Gerard Meszaros:
Subclase específica de la prueba
Pregunta : ¿Cómo podemos hacer código? comprobable cuando necesitamos acceder estado privado del SUT?
Respuesta : agrega métodos que exponen la Estado o comportamiento requerido por la prueba. a una subclase del SUT.
... Si el sistema bajo prueba (SUT) no estaba Diseñado específicamente para ser comprobable, podemos encontrar que la prueba no puede obtener Acceso a estado que debe Inicializar o verificar en algún momento en la prueba.
El artículo también explica cuándo usarlo y qué riesgos conlleva.
Coloque el código DUnit dentro de su unidad. A continuación, puede acceder a cualquier cosa que desee.
En general, cuando estoy en esta situación, a menudo me doy cuenta de que estoy violando el principio de responsabilidad única. Por supuesto, no sé nada sobre su caso específico, pero PUEDE, que los métodos privados deberían estar en su propia clase. El TAuth tendría una referencia a esta nueva clase en su sección privada.
Con RTTI extendido (Delphi 2010 y más reciente), invocar métodos privados a través de RTTI es otra opción. Esta solución también es la respuesta mejor calificada en ¿Cómo pruebo una clase que tiene métodos privados, campos o clases internas?
{$IFNDEF UNITEST}
private
{$ENDIF}
Solución simple, que apenas es un hack. Con frecuencia necesito probar métodos privados y esta técnica agrega la menor complicación posible.