Unit Test a CRUD Controller MVC

0

Ho esaminato le risposte relative a questo, ma non sembrano risolvere il mio problema.

Sono un gruppo di test e test abbastanza nuovo nel suo complesso. Ho appena terminato una piccola applicazione web utilizzando ASP.NET Core MVC e volevo scrivere test per i progetti. Sto usando xUnit e Moq.

Il progetto ha un livello di business logic che contiene la logica di business per l'app.

Sto scrivendo test per i controller, ma i controller contengono principalmente operazioni CRUD che utilizzano il livello di repository. I miei test per il controller prevedono l'utilizzo di un database in memoria poiché questo è il modo consigliato per ASP.NET Core MVC.

Tuttavia, ritengo che ciò che sto facendo non sia più unit test, ma test di integrazione dal momento che sto testando un database.

Avevo pensato di scrivere test di integrazione per il livello del repository e quindi unit test per i controller in modo tale che i controllori non dovessero controllare le operazioni del database.

Voglio sapere se questo è il modo giusto per andare o se c'è un altro modo.

Grazie. [Modificare]. Grazie @ greg-burghardt per la risposta. Ho fatto un errore nella mia domanda, in realtà intendevo scrivere che ho un livello di logica aziendale. Inoltre sto usando EF, e credo che si prenda cura del repository. I miei controller utilizzano l'interfaccia della BLL richiesta. Esempio

public class PaymentController : ControllerBase
{
    private readonly IConfiguration _config;
    private readonly IPaymentsBL _paymentsBL;
    private readonly ILogger _logger;

    public PaymentsController(IConfiguration config, IPaymentsBL paymentsBL, ILogger<PaymentsController> logger)
    {
        _config = config;
        _paymentsBL = paymentsBL;
        _logger = logger;
    }
}

E l'implementazione,

public class PaymentsBL : GenericBL<MPayments>, IPaymentsBL
{
    private readonly WellaPatientDbContext _db;

    public PaymentsBL(WellaPatientDbContext db)
    {
        _db = db;
    }

    public IQueryable<MPayments> GetByPatientId(Guid id)
    {
        return _db.MPayments.Where(x => x.PaymentId == id);
    }
}

Inoltre, hai detto che sto colpendo un vero database con i miei test. Non capisco dato che sto usando un database in memoria.

Quindi, se ho capito bene, i test per il livello della logica aziendale sono i più importanti. Grazie

    
posta elfico 24.09.2018 - 13:56
fonte

2 risposte

1

Ci sono due problemi principali con il design attuale che mi saltano addosso:

  1. Il livello del repository contiene la logica aziendale. Nessuna logica aziendale dovrebbe risiedere qui. Nel repository deve esistere solo la logica di persistenza (ad esempio la mappatura dei dati e le query SQL).

  2. Stai colpendo un vero database con i tuoi test.

Risolvere questi problemi in modo da poter scrivere test unitari richiede diverse correzioni:

  1. Sposta la "business logic" nel proprio set di classi, siano essi Domain Models o qualche sorta di "servizio" o "use case" classi

  2. Definisci le interfacce per i tuoi repository e chiedi ai controller di conservare i riferimenti ai repository con l'interfaccia come loro tipo.

  3. Esporre un costruttore pubblico sulle classi controller che accetta un repository tramite la sua interfaccia.

Scrivere test per la logica di persistenza non è una cosa negativa. Se si utilizza un ORM come NHibernate o Entity Framework a volte si desidera test di convalida dei mapping dei dati.

Scrivere test per la business logic è un'idea formidabile.

La scrittura di test per la logica di interazione in un controller richiede molte impostazioni per molto meno beneficio, specialmente quando hai refactato le cose in modo che i repository contengano solo la logica di persistenza e un altro set di classi contenga la logica di business.

Mantenere le dipendenze per le classi correlate "servizio" o "caso d'uso" chiaro, quindi impostare i test unitari è facile.

    
risposta data 24.09.2018 - 14:07
fonte
0

However, I feel what I am doing is no longer unit tests but integration tests since I am testing against a database.

Quindi, a chi importa? Non importa se qualcuno classificherebbe il tuo test come un test unitario o un test di integrazione, ciò che conta è è un test utile?

Se è veloce, informativo, ripetibile e corretto, è un buon test. Per ragioni inutili, la gente si blocca molto sulla terminologia in questo settore. Non importa. Scriviamo test perché vogliamo una garanzia qualitativa che (probabilmente) non abbiamo introdotto deviazioni impreviste nel comportamento del sistema, quindi se lo fai e qualcuno ti sta dando dolore la base "utilizza un database in memoria, quindi tecnicamente non è un test unitario", basta chiamarlo un test automatico e continuare a scrivere buoni test automatici.

    
risposta data 25.09.2018 - 17:29
fonte