2015-10-15 20 views
6

Ho un lavoro in cui ho un DbContext IDisposable. Vorrei testare l'unità di questo lavoro senza colpire in un database. Quali opzioni devo fare questo?Come gestire un repository IDisposable con Unity?

Im utilizzando l'assembly Fakes predefinito 'di Microsoft.

Il mio lavoro:

public void Work() 
{ 
    do 
    { 
     //code here     
     using (var repository = new Repository<User>()) 
     { 
      repository.Save(user); 
     } 

    } while (true); 
} 

sto cercando di testare e in questa parte del test viene a mancare perché in realtà crea una nuova istanza della classe Repository.

La mia prova Metodo:

using (ShimsContext.Create()) 
{ 
    Data.Repository.Fakes.ShimRepository<Domain.Fakes.ShimUser>.Constructor = (a) => { }; 

    Data.Repository.Fakes.ShimRepository<Domain.Fakes.ShimUser>.AllInstances.SaveT0 = (a, b) => 
    { 
    }; 

    var service = GetService(); 
    service.Work(); //Throws exception 
} 

Come posso fingere questo metodo Save?

+1

vedere Dipendenza iniezione: è necessario consentire il passaggio di un parametro in Work() o almeno in servizio, altrimenti crea sempre uno reale. –

+0

Non ho familiarità con Fakes, ma forse non è abbastanza completo per le tue esigenze. So che questo è banale con una libreria come Moq (https://github.com/Moq/moq4). –

+0

Non sarebbe nemmeno banale con Moq, poiché sta creando un'istanza concreta effettiva del repository nell'Opera. –

risposta

7

Hai violato DIP qui, rendendo l'unità testare il tuo servizio molto più difficile di quanto dovrebbe essere. Dovresti anche evitare i repository generici e favorire lo role interfaces.

Invece, iniettare un'astrazione al proprio servizio del repository, ad es. IUsersRepository che definisce il metodo Save. Quindi, nel test dell'unità del servizio, è sufficiente utilizzare un'implementazione stub di IUsersRepository.

+0

Sì, ma per quanto riguarda lo smaltimento dell'oggetto? Se lo inietto una volta, il lavoro verrà eseguito per sempre con la prima istanza del contesto. – gog

+0

Lo smaltimento è un dettaglio di implementazione dell'implementazione dell'entità Framework dell'astrazione. Pertanto lo smaltimento viene effettuato all'interno ad es. EntityFrameworkUsersRepository. – devdigital

2

falsi tendono a rivelare che il codice non segue correttamente il D in SOLID dal momento che si sta creando dipendenze all'interno della vostra classe invece di trasmetterli in.

Un modello molto meglio sarebbe per creare un'interfaccia ISaveRepository che a sua volta implementa IDisposable con un metodo esposto Save(). Dovresti quindi iniettare un'istanza del tuo repository nella tua classe. Ciò ti consentirà di soddisfare il test delle dichiarazioni usando, oltre a implementare una simulazione che definisce un metodo .Save() che non colpisce il database.

public class Test 
{ 
    private readonly ISaveRepository _userRepository; 

    public Test(ISaveRepository userRepository) 
    { 
     _userRepository = userRepository; 
    } 

    public void Work() 
    { 
     using (_userRepository) 
     { 
      var cont = true; 
      do 
      {    
       _userRepository.Save(new User()); 
       cont = false; 
      } while (cont); 
     } 
    } 
} 

public interface ISaveRepository : IDisposable 
{ 
    void Save<T>(T model); 
} 

public class Repository<T> : ISaveRepository 
{ 
    public void Dispose() { } 
    public void Save<TT>(TT model) {} 
} 

public class User {} 
+0

Come Dispose non sarebbe richiesto per molte implementazioni? – gog

+0

L'implementazione dello stub richiede una soluzione? Sarà necessario disporre di un repository XML? Un repository di chiamate al servizio web richiede una soluzione? ecc. ecc. – devdigital

+0

@ggui Suppongo quindi che in origine si stesse ricreando la connessione per evitare di mantenere una connessione per un lungo periodo di tempo? –

Problemi correlati