delphi - ¿Cómo puedo probar métodos privados con DUnit?
unit-testing (7)
No necesita hacerlos públicos. Protegido hará. Luego puede subtipificar la clase para las pruebas unitarias y explorar los métodos protegidos. Ejemplo:
type
TAuth = class(TDataModule)
protected
procedure MethodIWantToUnitTest;
public
procedure PublicMethod;
end;
Ahora puede subtipificarlo para su 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 probar están haciendo cosas tan íntimamente con el módulo de datos que no es seguro tener nada más que privado, entonces realmente debería considerar refactorizar los métodos para segregar el código que necesita ser unidad. probado y el código que accede a las entrañas del módulo de datos.
Tengo una clase en la que estoy probando unidades 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 unitaria para esta clase, tengo que hacer públicos todos los métodos.
¿Hay alguna manera diferente de declarar los métodos privados para que pueda probarlos pero no son públicos?
Recomiendo el libro " XUnit Test Patterns " de Gerard Meszaros:
Pregunta : ¿Cómo podemos hacer que el código sea comprobable cuando necesitamos acceder al estado privado del SUT?
Respuesta : Agregue métodos que expongan el estado o el comportamiento que necesita la prueba a una subclase del SUT.
... Si el sistema bajo prueba (SUT) no fue diseñado específicamente para ser comprobado, podemos encontrar que la prueba no puede obtener acceso para indicar que debe inicializarse o verificar en algún momento de la prueba.
El artículo también explica cuándo usarlo y qué riesgos conlleva.
Coloque el código de DUnit dentro de su unidad. A continuación, puede acceder a cualquier cosa que desee.
En general, cuando me meto 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 QUIZÁ, que los métodos privados deben ser de su propia clase. El TAuth tendría una referencia a esta nueva clase en su sección privada.
{$IFNDEF UNITEST}
private
{$ENDIF}
Solución simple, que difícilmente es un truco. Con frecuencia necesito probar métodos privados y esta técnica agrega la menor complicación posible.
Es un poco raro, pero me gusta usar esta directiva de compilación condicional:
{$IfNDef TEST}
private
{$EndIf}
El proyecto de prueba de unidad debe definir TEST en el project → conditional defines
.
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 algunas ventajas sobre la subclasificación u otros enfoques:
- Sin complejidad adicional: no hay clases adicionales en su código
- Nadie puede "erróneamente" subclasificar y anular tu clase: conservas tu arquitectura
- Cuando dice que un método está protegido, de alguna manera espera que se anule. Usted está diciendo esto para quién está leyendo su código. Un método protegido que no debe ser anulado confundirá a los lectores de su código, rompiendo mi primer principio de programación: "el código debe escribirse para ser leído por otros seres humanos".
- DUnit está en su propia unidad, no se incluye en todas partes
- No tocas el sucio RTTI.
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 poner 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.
Con Extended RTTI (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 mejor respuesta en ¿Cómo pruebo una clase que tiene métodos privados, campos o clases internas?