2012-02-05 10 views
5

Non riesco a far funzionare correttamente il mio test dell'unità. Funziona in un test di integrazione in cui ho effettivamente colpito l'Archiviazione tabelle di Azure. Il problema credo sia il beffeggiamento della proprietà QueryableEntities che retrona un Queryable dalla simulazione ma restituisce un DataServiceQuery dalla classe ServiceContext. È possibile creare uno stub di tipo DataServiceQuery che restituisce una query?Come si esegue il test dell'unità per la query di Windows Azure Table con uno stub utilizzando Moq?

Questo è il mio codice:

prova

[TestMethod] 
    public void GetAExistingWordInStorageShouldReturnCorrectWord() 
    { 

     Word expected = new Word(Dictionaries.Swedish.ToString(), "Word", "Word"); 

     List<Word> Words = new List<Word>(); 
     Words.Add(new Word(Dictionaries.Swedish.ToString(), "Word", "Word")); 

     IQueryable<Word> WordQueryable = Words.AsQueryable<Word>(); 

     var mock = new Mock<IServiceContext<Word>>(); 
     mock.Setup(x => x.QueryableEntities).Returns(WordQueryable); 

     DictionaryRepository dr = new DictionaryRepository(Models.Dictionaries.Swedish, "testdictionaries"); 
     dr.Context = mock.Object; 

     Word result = dr.GetWord(expected.Text, false); 

     Assert.AreEqual(expected, result); 
    } 

interfaccia IServiceContect

public interface IServiceContext<TEntity> 
{ 
    IQueryable<TEntity> QueryableEntities {get;} 
} 

ServiceContext Classe

public class ServiceContext<TEntity> : TableServiceContext, IServiceContext<TEntity> where TEntity : TableServiceEntity 
{ 

    private readonly string tableName; 

    public ServiceContext(CloudStorageAccount account, String tableName) 
     : base(account.TableEndpoint.ToString(), account.Credentials) 
    { 
     this.tableName = tableName; 
     this.IgnoreResourceNotFoundException = true; 
    } 

    public IQueryable<TEntity> QueryableEntities 
    { 
     get 
     { 
      return CreateQuery<TEntity>(tableName); 
     } 
    } 

} 

dizionario Repository

 public class DictionaryRepository : IDictionaryRepository 
{ 
    public Dictionaries Dictionary { get; set; } 
    public String TableName; 

    public IServiceContext<Word> Context; 

    public DictionaryRepository(Dictionaries dictionary) 
     : this(dictionary, "dictionaries") 
    { 
    } 

    public DictionaryRepository(Dictionaries dictionary, String tableName) 
    { 
     Dictionary = dictionary; 
     this.TableName = tableName; 
     CloudStorageAccount account = CloudStorageAccount.Parse(***); 
     Context = new ServiceContext<Word>(account, this.TableName); 
    } 

    public List<Tile> GetValidTiles() 
    { 
     throw new NotImplementedException(); 
    } 

    public Type ResolveEntityType(String name) 
    { 
     return typeof(Word); 
    } 

    public Word GetWord(string word, Boolean useCache = false) 
    { 

     var q = this.Context.QueryableEntities.Where(x => x.PartitionKey == Dictionary.ToString() && x.RowKey == word).AsTableServiceQuery(); 

     Word result = q.Execute().SingleOrDefault(); 

     if (result == null) 
      return null; 

     return result; 

    }} 

sto ottenendo il seguente errore

Errore:

ArgumentNullException was unhandeled by user code 
    Value cannot be null. 
    Parameter name: query 

ottengo l'errore quando si chiama .AsTableServiceQuery() nella riga seguente in Classe DictionaryRepository:

var q = this.Context.QueryableEntities.Where(x => x.PartitionKey == Dictionary.ToString() && x.RowKey == word).AsTableServiceQuery(); 
+0

Considerate avvolgendo il codice di Microsoft nella tua classe che implementa un'interfaccia semplificata. – TrueWill

risposta

1

Non hai citato l'errore che stai ricevendo, ma dal momento che il QueryableEntities è una proprietà di sola lettura provare a utilizzare mock.SetupGet invece di mock.Setup.

EDIT:

Esaminando ulteriormente il problema è che il metodo di estensione .AsTableServiceQuery() tenta di lanciare il IQueryable<T> ad un DataServiceQuery<T>, che fallisce causando l'eccezione nullo.

C'è un post di Frederic Boerr su come eseguire il test dell'unità con l'archiviazione della tabella che dovrebbe aiutarti. Windows Azure Storage: TDD and mocks

+0

Non ha funzionato. Ho aggiornato la mia domanda con l'errore che sto ottenendo. – Frej

0

So che hai chiesto espressamente come farlo usando Moq, e non ho una risposta a questo, ma ho capito come fare qualcosa di simile usando Fakes.

http://azurator.blogspot.com/2013/07/unit-testing-azure-table-storage-queries.html

In sostanza è possibile creare uno Shim su CloudTableQuery<T> che legge l'oggetto Expression la query utilizza e applica la stessa logica per il codice utilizzando IEnumerable come questo:

[TestMethod] 
public void here_is_my_test() 
{ 
    IEnumerable<MyEntityType> fakeResults = GetFakeResults(); 

    using (ShimsContext.Create()) 
    { 
     InterceptCloudTableQueryExecute<MyEntityType>(fakeResults); 

     DoQuery(); 

     AssertStuff(); 
    } 
} 

public void InterceptCloudTableQueryExecute<T>(IEnumerable<T> result) 
{ 
    var query = result.AsQueryable(); 

    ShimCloudTableQuery<T>.AllInstances.Execute = (instance) => 
    { 
     // Get the expression evaluator. 
     MethodCallExpression ex = (MethodCallExpression)instance.Expression; 

     // Depending on how I called CreateQuery, sometimes the objects 
     // I need are nested one level deep. 
     if (ex.Arguments[0] is MethodCallExpression) 
     { 
      ex = (MethodCallExpression)ex.Arguments[0]; 
     } 

     UnaryExpression ue = ex.Arguments[1] as UnaryExpression; 

     // Get the lambda expression 
     Expression<Func<T, bool>> le = ue.Operand as Expression<Func<T, bool>>; 

     query = query.Where(le); 
     return query; 
    }; 
} 
Problemi correlati