qual è il modo corretto / migliore per popolare una proprietà secondaria di un modello MVC e come eseguo il test dell'unità?

3

Sto costruendo un'applicazione web ASP.NET MVC 3 (.NET 4) e sto provando a testare l'unità il più possibile.

Ho un'azione del controller Details(int customerId) che dovrebbe mostrare una vista il cui modello è un Customer

public class Customer
{
    public int? Id { get; set; }

    [Required]
    [Display(Name = "Customer Name")]
    public string Name { get; set; }

    ...

    public IList<CustomerComment> Comments { get; set; }
} 

L'azione del controller è la seguente:

public ActionResult Details(int customerId)
{
    var model = service.Get(customerId);
    if (model != null)
        return View(model);

    return RedirectToAction("Index");
}

Come puoi vedere, questo chiama direttamente service.Get

public Customer Get(int id)
{
    return repository.Get(id);
}

Il servizio ha una ICustomerRepository iniettata e chiama direttamente il metodo Get di quel repository.

La mia domanda riguarda il popolamento della raccolta Comments .

Come / dove dovrebbe essere popolato Comments e come posso testarlo?

La visualizzazione Details è l'unica posizione che visualizza l'elenco di commenti, quindi ha bisogno di questi dati. Posso vedere due modi per popolare questo.

  1. Fai tutto nell'implementazione ICustomerRepository.Get .
    Ciò potrebbe portare a una situazione in linea in cui sto utilizzando Get ma non a visualizzare i commenti. Ciò significherebbe che sto facendo un costoso (forse) JOIN ma non utilizzando i risultati.

  2. Avere un ICustomerCommentsRepository/Service iniettato nel mio servizio o controller che viene utilizzato per popolare Comments quando richiesto.

C'è una preferenza?

In secondo luogo, come metteresti alla prova questo?

Nella seconda istanza, potrei affermare che ICustomerCommentsRepository.Populate(Customer customer) è chiamato sul mio mock dal Controller / Servizio.

Nella prima situazione tutta la responsabilità risiede nel mio repository quindi in senso unitario, non è testabile in quanto l'implementazione concreta utilizzata nell'app effettiva deve parlare al DB e quindi è un test di integrazione.

Mi manca qualcosa? La ICustomerCommentsRepository sarebbe una cattiva idea?

    
posta Greg B 24.08.2011 - 23:51
fonte

1 risposta

2

IMO Dovresti conservare i tuoi repository per radice di aggregazione

Potresti non fare DDD, tuttavia credo che questo sia ancora un consiglio valido nel tuo caso.

Stai recuperando un cliente da un repository (db, in archivio di memoria, elenco di clienti, ecc.) e potresti voler o meno voler popolare il tuo elenco di commenti.

Spezza le funzioni di ICustomerRepository fino a rappresentare le tue strategie di recupero

Sembra che tu abbia bisogno di 2 strategie di recupero.

  1. Recupera il cliente ma carica i commenti fino a quando non è necessario (commenti di caricamento pigro)
  2. Recupera i commenti del cliente e del carico desideroso (ne avranno sempre bisogno)

Questo determinerà i metodi che è possibile implementare su ICustomerRepository

// lazy loads comments list as these may not be used
public Customer Get(long customerId) {}

// eager loads comments (as effeciently as possible)
public Customer GetWithComments(long customerId) {}

Crea un repository separato solo se lo utilizzerai direttamente

Crea un repository IComments separato solo se lo utilizzi direttamente. L'utilizzo indiretto insieme a un altro repository separa una preoccupazione singolare. Un pattern di repository non è limitato a una singola tabella ma a una singola responsabilità.

    
risposta data 25.08.2011 - 01:27
fonte

Leggi altre domande sui tag