Pregunta

He desarrollado algunas clases con comportamiento similar, todas implementan la misma interfaz.Implementé una fábrica que crea el objeto apropiado y devuelve la interfaz.Estoy escribiendo una prueba unitaria para la fábrica.Todo lo que obtienes es una interfaz para el objeto.¿Cuál es la mejor forma de comprobar que la fábrica ha funcionado correctamente?

Me gustaría saber la respuesta en Java, pero si hay una solución que cruce idiomas me gustaría saberla.

Número 2.en la respuesta, ¿se haría como la otra respuesta?Si es así, también marcaré la otra respuesta como aceptada y reformularé mi pregunta para abordar tanto una fábrica donde se devuelve una interfaz y no tienes idea de qué tipo de clase concreta implementó la interfaz, como el caso en el que sí sabes qué clase concreta era. usado.

¿Fue útil?

Solución

Como no sé cómo es su método de fábrica, todo lo que puedo aconsejar ahora es

  1. Verifique que el objeto sea la implementación concreta correcta que estaba buscando:

    IMyInterface fromFactory = factory.create(...);  
    Assert.assertTrue(fromFactory instanceof MyInterfaceImpl1);
    
  2. Puede verificar si la fábrica configuró las instancias concretas con variables de instancia válidas.

Otros consejos

Lo que estás intentando hacer no es una prueba unitaria.

Si prueba si los objetos devueltos son instancias de clases concretas específicas, no está realizando pruebas unitarias.Estás realizando pruebas de integración.Si bien las pruebas de integración son importantes, no son lo mismo.

En las pruebas unitarias, solo necesita probar el objeto en sí.Si afirma el tipo concreto de los objetos abstractos devueltos, está probando la implementación del objeto devuelto.

Pruebas unitarias sobre objetos en general

Cuando se realizan pruebas unitarias, hay cuatro cosas que se deben afirmar:

  1. Los valores de retorno de las consultas (métodos no nulos) son los que espera que sean.
  2. Los efectos secundarios de los comandos (métodos nulos) modifican el objeto en sí como usted espera que lo hagan.
  3. Se reciben los comandos enviados a otros objetos (esto generalmente se hace mediante simulacros).

Además, sólo desea probar lo que se puede observar desde una instancia de objeto, es decir.la interfaz pública.De lo contrario, quedará vinculado a un conjunto específico de detalles de implementación.Esto requeriría que cambie sus pruebas cuando esos detalles cambien.

Fábricas de pruebas unitarias

Las pruebas unitarias en fábricas son realmente poco interesantes, porque no le interesa el comportamiento de los objetos devueltos por las consultas.Ese comportamiento se prueba (con suerte) en otro lugar, presumiblemente mientras la unidad prueba ese objeto en sí.Lo único que realmente le interesa es si el objeto devuelto tiene o no la información correcta. tipo, que está garantizado si su programa se compila.

Como las Fábricas no cambian con el tiempo (porque entonces serían "Constructores", que es otro patrón), no hay comandos para probar.

Las fábricas son responsables de crear instancias de objetos, por lo que no deberían depender de otras fábricas para que lo hagan por ellos.Ellos podría Dependemos de un Builder, pero aun así, se supone que no debemos probar la corrección del Builder, solo si el Builder recibe o no el mensaje.

Esto significa que todo lo que tienes que probar en las fábricas es si envían o no los mensajes a los objetos de los que dependen.Si utiliza la inyección de dependencia, esto es casi trivial.Simplemente simule las dependencias en sus pruebas unitarias y verifique que reciban los mensajes.

Resumen de fábricas de pruebas unitarias

  1. ¡No pruebes el comportamiento ni los detalles de implementación de los objetos devueltos!¡Su fábrica no es responsable de la implementación de las instancias de objetos!
  2. Pruebe si se reciben o no los comandos enviados a las dependencias.

Eso es todo.Si no hay dependencias, no hay nada que probar.Excepto tal vez para afirmar que el objeto devuelto no es un null referencia.

Fábricas de pruebas de integración

Si tiene el requisito de que el tipo de objeto abstracto devuelto sea una instancia de un tipo concreto específico, entonces esto se incluye en las pruebas de integración.

Otros aquí ya han respondido cómo hacer esto usando el instanceof operador.

@ cem-catikkas Creo que sería más correcto comparar los valores getClass().getName().En el caso de que la clase MyInterfaceImpl1 tenga una subclase, su prueba podría fallar, ya que la subclase es una instancia de MyInterfaceImpl1.Lo reescribiría de la siguiente manera:

IMyInterface fromFactory = factory.create(...);  
Assert.assertEquals(fromFactory.getClass().getName(), MyInterfaceImpl1.class.getName());

Si crees que esto podría fallar de alguna manera (no lo puedo imaginar), haz las dos verificaciones.

if (myNewObject instanceof CorrectClass)
{
    /* pass test */
}

actualizar:

No sé por qué se rebajó esto, así que lo ampliaré un poco...

public void doTest()
{
    MyInterface inst = MyFactory.createAppropriateObject();
    if (! inst instanceof ExpectedConcreteClass)
    {
        /* FAIL */
    }
}

Si su fábrica devuelve una instancia concreta, puede usar el @Parámetros anotación para obtener una prueba unitaria automática más flexible.

package it.sorintlab.pxrm.proposition.model.factory.task;

import org.junit.Test;

import java.util.Arrays;
import java.util.Collection;

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import static org.junit.Assert.*;

@RunWith(Parameterized.class)
public class TaskFactoryTest {

    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
                { "sas:wp|repe" , WorkPackageAvailabilityFactory.class},
                { "sas:wp|people", WorkPackagePeopleFactory.class},
                { "edu:wp|course", WorkPackageCourseFactory.class},
                { "edu:wp|module", WorkPackageModuleFactory.class},
                { "else", AttachmentTaskDetailFactory.class}
        });
    }

    private String fInput;
    private Class<? extends TaskFactory> fExpected;

    public TaskFactoryTest(String input, Class<? extends TaskFactory> expected) {
        this.fInput = input;
        this.fExpected = expected;
    }

    @Test
    public void getFactory() {
        assertEquals(fExpected, TaskFactory.getFactory(fInput).getClass());
    }
}

Este ejemplo está hecho usando Junit4.Puedes notar que con solo una línea de código puedes probar todo el resultado de tu método Factory.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top