Domanda

Ho sviluppato alcune classi con comportamento simile, implementano tutte la stessa interfaccia.Ho implementato una factory che crea l'oggetto appropriato e restituisce l'interfaccia.Sto scrivendo un test unitario per la fabbrica.Tutto ciò che ottieni è un'interfaccia per l'oggetto.Qual è il modo migliore per verificare che la fabbrica abbia funzionato correttamente?

Vorrei conoscere la risposta in Java, ma se esiste una soluzione che attraversa le lingue mi piacerebbe saperla.

Numero 2.nella risposta, si farebbe come l'altra risposta?In tal caso contrassegnerò anche l'altra risposta accettata e riformulerò la mia domanda per affrontare sia una fabbrica in cui viene restituita un'interfaccia e non hai idea di quale tipo di classe concreta abbia implementato l'interfaccia, sia il caso in cui sai quale classe concreta era usato.

È stato utile?

Soluzione

Dato che non so come sia il tuo metodo di fabbrica, tutto ciò che posso consigliarti in questo momento è di farlo

  1. Controlla che l'oggetto sia la corretta implementazione concreta che stavi cercando:

    IMyInterface fromFactory = factory.create(...);  
    Assert.assertTrue(fromFactory instanceof MyInterfaceImpl1);
    
  2. È possibile verificare se la fabbrica ha impostato le istanze concrete con variabili di istanza valide.

Altri suggerimenti

Quello che stai cercando di fare non è unit test

Se verifichi se gli oggetti restituiti sono o meno istanze di classi concrete specifiche, non stai effettuando test unitari.Stai testando l'integrazione.Sebbene il test di integrazione sia importante, non è la stessa cosa.

Nel test unitario, devi solo testare l'oggetto stesso.Se affermi il tipo concreto degli oggetti astratti restituiti, stai testando l'implementazione dell'oggetto restituito.

Unit test su oggetti in generale

Durante il test unitario, ci sono quattro cose che vuoi affermare:

  1. I valori restituiti dalle query (metodi non void) sono quelli che ti aspetti che siano.
  2. Gli effetti collaterali dei comandi (metodi void) modificano l'oggetto stesso come previsto.
  3. I comandi inviati ad altri oggetti vengono ricevuti (questo di solito viene fatto utilizzando mock).

Inoltre, vuoi solo testare ciò che potrebbe essere osservato da un'istanza di oggetto, ad es.l'interfaccia pubblica.Altrimenti, ti leghi a una serie specifica di dettagli di implementazione.Ciò richiederebbe di modificare i test quando tali dettagli cambiano.

Fabbriche di test unitari

I test unitari sulle fabbriche sono davvero poco interessanti, perché non sei interessato al comportamento degli oggetti restituiti dalle query.Questo comportamento è (si spera) testato altrove, presumibile durante il test unitario dell'oggetto stesso.Ti interessa davvero solo se l'oggetto restituito ha o meno la correttezza tipo, che è garantito se il tuo programma viene compilato.

Poiché le fabbriche non cambiano nel tempo (perché in tal caso sarebbero "Costruttori", che è un altro modello), non ci sono comandi da testare.

Le fabbriche sono responsabili dell'istanziazione degli oggetti, quindi non dovrebbero dipendere da altre fabbriche per farlo per loro.Essi Potrebbe dipendono da un Costruttore, ma anche così, non dovremmo testare la correttezza del Costruttore, ma solo se il Costruttore riceve o meno il messaggio.

Ciò significa che tutto ciò che devi testare sulle Factory è se inviano o meno i messaggi agli oggetti da cui dipendono.Se usi Dependency Injection, questo è quasi banale.Basta prendere in giro le dipendenze nei test unitari e verificare che ricevano i messaggi.

Riepilogo delle fabbriche di test unitari

  1. Non testare il comportamento né i dettagli di implementazione degli oggetti restituiti!La tua Factory non è responsabile dell'implementazione delle istanze degli oggetti!
  2. Verifica se i comandi inviati alle dipendenze vengono ricevuti o meno.

Questo è tutto.Se non ci sono dipendenze, non c'è nulla da testare.Tranne forse per affermare che l'oggetto restituito non è a null riferimento.

Fabbriche di test di integrazione

Se hai il requisito che il tipo di oggetto astratto restituito sia un'istanza di un tipo concreto specifico, allora questo rientra nel test di integrazione.

Altri qui hanno già risposto come farlo utilizzando il file instanceof operatore.

@cem-catikkas Penso che sarebbe più corretto confrontare i valori getClass().getName().Nel caso in cui la classe MyInterfaceImpl1 abbia una sottoclasse, il test potrebbe essere interrotto, poiché la sottoclasse è un'istanza di MyInterfaceImpl1.Io lo riscriverei così:

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

Se pensi che questo possa fallire in qualche modo (non riesco a immaginare), fai le due verifiche.

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

aggiornamento:

Non so perché questo sia stato cancellato, quindi lo espanderò un po'...

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

Se la tua Factory restituisce un'istanza concreta puoi utilizzare il file @Parametri annotazione per ottenere uno unit test automatico più flessibile.

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());
    }
}

Questo esempio è realizzato utilizzando Junit4.Puoi notare che con una sola riga di codice puoi testare tutto il risultato del tuo metodo Factory.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top