2012-02-05 8 views
5

Nie mogę sprawdzić, czy mój test jednostki działa prawidłowo. Działa w teście integracji, który mam, gdzie faktycznie trafi do magazynu tabel Azure. Problem, który prawdopodobnie jest kpiną z usługi QueryableEntities, która powoduje retransmitowanie kwerendy ze strony próbnej, ale zwraca DataServiceQuery z klasy ServiceContext. Czy jest możliwe utworzenie kodu pośredniczącego typu DataServiceQuery, który zwraca Queryable?W jaki sposób mogę przetestować zapytanie o tabelę Windows Azure za pomocą kodu pośredniczącego za pomocą funkcji Moq?

To jest mój kod:

test

[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); 
    } 

interfejs IServiceContect

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

ServiceContext Klasa

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); 
     } 
    } 

} 

słownik 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; 

    }} 

Dostaję następujący błąd

Błąd:

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

pojawia się błąd podczas wywoływania .AsTableServiceQuery() w następującym wierszu w DictionaryRepository klasa:

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

Rozważmy zawijania kodu Microsoft we własnej klasie, która implementuje uproszczony interfejs. – TrueWill

Odpowiedz

1

Nie wspomniano błąd dostajesz, ale ponieważ QueryableEntities jest właściwością tylko do odczytu spróbuj mock.SetupGet zamiast mock.Setup.

EDIT:

Patrząc na niego dodatkowo problemem jest to, że metoda rozszerzenie .AsTableServiceQuery() próbuje rzucać IQueryable<T> Do DataServiceQuery<T>, która nie powoduje wyjątku null.

Istnieje post Frederica Boerr'a na temat przeprowadzania testów jednostkowych z przechowywaniem tabel, które powinny ci pomóc. Windows Azure Storage: TDD and mocks

+0

Nie działa. Zaktualizowałem moje pytanie z powodu otrzymywanego błędu. – Frej

0

Wiem, że specjalnie zapytałeś, jak to zrobić, używając Moq, i nie mam na to odpowiedzi, ale wymyśliłem, jak zrobić coś podobnego za pomocą Fakes.

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

Zasadniczo można utworzyć Shim na CloudTableQuery<T> które odczytuje obiekt Expression kwerenda korzysta i stosuje tę samą logikę do IEnumerable przy użyciu kodu tak:

[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; 
    }; 
} 
Powiązane problemy