È possibile utilizzare AspectJ o AOP in generale per testare la gestione delle eccezioni?

1

Sto leggendo il capitolo di un libro ("Controlled Exception Test" in "Test del test orientato agli oggetti" ) sulla verifica della gestione delle eccezioni in un sistema in esecuzione (non a livello di unità). La conclusione è che è difficile attivare automaticamente un'eccezione in un dato livello nel sistema, quindi simulare una causa per un'eccezione.

L'uso di AspectJ o di un altro approccio AOP non risolverebbe il problema?

Con AOP posso creare un aspetto che genererà un'eccezione prevista e collegarlo al metodo chiamato prima della gestione delle eccezioni.

    
posta dzieciou 01.09.2013 - 23:08
fonte

1 risposta

3

I framework AOP normalmente rispondono a preoccupazioni trasversali. La gestione delle eccezioni è una di queste. Posso dire che voglio registrare l'invocazione di ogni metodo nel mio livello aziendale e voglio anche intercettare e registrare ogni eccezione generata da qualsiasi metodo in quel livello aziendale.

Quando si tratta di test delle unità, non voglio testare che il framework orientato all'aspetto intercetta la chiamata al metodo e registri l'eccezione. Le persone che hanno scritto il framework dell'aspetto hanno già fatto questo test e sappi che funziona.

Quello che probabilmente vorresti testare è come si comporta il codice quando viene lanciata l'eccezione. Normalmente ottieni questo con strutture di derisione. Ad esempio, nel mio livello aziendale ho un metodo che mi restituisce gli ultimi film:

[LogExceptionThroughAOPFramework]
public IEnumerable<FilmSummary> GetLatestFilms()
{
   var latestFilms = _repository.GetLatestFilms();
   var latestFilmsDTO = Mapper.Map<FilmSummaryDTO>(latestFilms);
   return latestFilmsDTO;
}

Ora, il metodo sopra può fallire quando chiama _repository.GetLatestFilms();

C'è anche un attributo immaginario chiamato LogExceptionThroughAOPFramework - intercetta una chiamata al metodo e registra l'eccezione.

Quando si tratta di testare questo metodo, non si desidera verificare che il framework AOP registri l'eccezione. È una dipendenza di terze parti e non vuoi fare affidamento su questa dipendenza. L'intercettazione è già stata testata da persone che hanno scritto il framework. Se tutta la gestione / registrazione delle eccezioni viene eseguita dal framework AOP, non è necessario testarlo. Invece, prova la logica di LogExceptionThroughAOPFramework e dovrebbe essere sufficiente.

Se non usi il framework AOP, usa un framework di simulazione. Ad esempio:

[TestMethod]
[ExpectedException(typeof(RelevantTypeOfException)]
public void GetLatestFilms_RepositoryThrowsException_ExpectExceptionToBePropagated
{
   var repository = new Mock<ILatestFilmsRepository>();
   repository.Expect(call => call.GetLatestFilms()).Throws(new RelevantTypeOfException());

   var client = new FilmClient(repository);
   // Throws exception
   client.GetLatestFilms();
}

Nel test precedente dico che mi aspetto di lanciare un'eccezione (attributo sopra il metodo di test). Quindi configuro il mio repository (mock) per lanciare un'eccezione quando provo a ottenere gli ultimi film. Alla fine, faccio un oggetto cliente e cerco di ottenere una lista degli ultimi film. Nel costruttore ho passato un deposito fittizio, che poi genera un'eccezione. Il test passerà come verrà generata l'eccezione.

Inoltre, hai detto:

With AOP I can create an aspect that will throw an expected exception and attach it to the method called before exception handling.

Se lo fai, allora cosa testerai? Se l'eccezione è generata da un aspetto, non testerai la tua logica aziendale. Testerai le eccezioni di lancio di aspetti. Non vedo alcun valore in questo.

Aggiorna

Potresti potenzialmente aggiungere un aspetto a qualunque cosa tu stia testando.

Dovresti aggiungere un aspetto per ogni test. Il tuo aspetto deve essere consapevole del contesto in cui viene eseguito, ovvero deve sapere che il codice è in esecuzione in un contesto di test.

Quindi, se volessi verificare come si comporta il sistema se il repository genera un'eccezione, dovrei scrivere qualcosa sulle righe di:

[ThrowExceptionOnlyDuringTest("TestScenario")]
[ThrowExceptionOnlyDuringTest("DifferentTestScenario")]
public IEnumerable<FilmSummary> GetLatestFilms()
{
   // Logic to retrieve films
}

Non so come si collegherebbe il test a questo aspetto. Per quanto posso vedere, questo non è molto diverso per impostare le aspettative sui mock. Aspect creerà un proxy per l'esecuzione del metodo e genererà un'eccezione. Il framework di simulazione farà esattamente lo stesso, ma in un modo più semplice.

Aggiornamento 2

Suppongo che nel tuo caso stai testando l'integrazione dell'intero sistema. Hai accesso a tutti i componenti e stai cercando di trovare un modo carino per far fallire questi componenti durante i test di integrazione. L'approccio AOP potrebbe funzionare qui, non sono ancora sicuro.

Che cosa succede nello scenario in cui non hai il controllo sui componenti con cui stai integrando? Ad esempio, se il tuo sistema comunica con il servizio di cambio valuta in un altro paese, non ci sarà modo di farlo fallire. In questo caso, prenderai semplicemente in giro questo servizio e fagli generare un'eccezione durante i test di integrazione. Per questo motivo, penso che abbia un test di integrazione con una simulazione che genera un'eccezione in alcuni scenari.

    
risposta data 01.09.2013 - 23:31
fonte

Leggi altre domande sui tag