Escribo una clase que heredará una interfaz. El código del cliente se escribirá para esa interfaz y la clase escrita para soportarlo. La idea es que más adelante escribiré otras clases para esa interfaz, y los objetos de esas dos clases diferentes deberían ser completamente intercambiables. En lugar de escribir una clase de prueba para esa primera clase, quiero escribir una para la interfaz.PHPUnit: escribir una clase de prueba para una interfaz y probar objetos usando una fábrica
Mi plan era escribir una clase de prueba que tomara un objeto de fábrica para el constructor (inyección de dependencia) y usar la fábrica para crear nuevas instancias de la clase bajo prueba.
De esta forma, si quisiera probar ClassA, podría pasar un objeto ClassAFactory al constructor de la clase de prueba, y si quería probar ClassB, pasaría un objeto ClassBFactory. Ambas clases están diseñadas para ser intercambiables, y dado que se supone que solo se deben probar los métodos públicos, esto parece ideal.
Pero, ¿qué tal probar el constructor? ¿Sería mejor escribir una clase de prueba abstracta e implementar pruebas de constructor en clases que hereden la clase de prueba abstracta (diferentes clases pueden crearse instancias de forma diferente)?
Si lo hiciera uso de la primera idea, supongo que tendría una clase de prueba para cada clase que se está probando, como:
class ClassATest extends [PHPUnit test case]
{
$myFactory = new ClassAFactory();
$myTest = new ClassTest($myFactory);
$myTest->test1();
$myTest->test2();
//etc.
}
¿Cuál es la mejor manera de hacer esto? Quiero hacer una prueba general, de modo que cuando escriba nuevas clases para implementar la interfaz común, simplemente pueda poner un objeto de las mismas pruebas que las usadas para las otras. Pero, dado que las diferentes clases tendrían diferentes constructores, ¿sería mejor escribir una clase de prueba abstracta y ampliarla para cada nuevo objeto? ¿Qué piensas?
En este ejemplo específico, las clases representarán destinatarios para una lista de correo. Aunque tendrán diferentes formas de hacer su trabajo, tomarán los mismos datos de un cliente y obtendrán los mismos resultados: completamente intercambiables. Me parece que si los objetos de diferentes clases que usan esa interfaz son intercambiables dentro del código del cliente, también deberían ser intercambiables dentro del código de prueba. Entonces, cuando digo que quiero probar la interfaz, lo que quiero decir es que quiero escribir una prueba en esa interfaz para probar una clase que usa esa interfaz. ¿Eso tiene sentido para ti? –
No, todavía no tiene sentido. No es así como entiendo que una interfaz funcione. Es posible que desee una clase base abstracta en lugar de una interfaz para implementar el código común. No estoy seguro de qué es diferente acerca de tus clases aparte de los datos. – liquorvicar
Digamos en clase, MailChimpRecipient usa la interfaz MailingListRecipient: el cliente codificado agrega a alguien a la lista configurando la dirección de correo electrónico y las propiedades del nombre del objeto del destinatario, y luego llama a un método para agregarlas. Ahora, ese método para la clase MailChimp usará la API de MailChimp para agregarlos. Digamos que en el futuro, quiero alojar mi propia lista de correo o usar otro proveedor, podría cambiar la clase con otra clase que use la interfaz MailingListRecipient. Esa clase puede hacer algo completamente diferente para agregar el destinatario, pero aún toma los mismos datos. –