[英]How do I unit test Windows Azure Table query with a stub using Moq?
我無法讓我的單元測試正常工作。
它在我有的集成測試中工作,它實際上會影響 Azure 表存儲。
我猜的問題是對QueryableEntities屬性的模擬,它從模擬中返回一個Queryable<Word>
但它從 ServiceContext 類中返回一個DataServiceQuery 。 是否可以創建返回可查詢的DataServiceQuery類型的存根?
這是我的代碼:
測試
[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);
}
IServiceContect 接口
public interface IServiceContext<TEntity>
{
IQueryable<TEntity> QueryableEntities {get;}
}
服務上下文類
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);
}
}
}
字典庫
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;
}}
我收到以下錯誤
錯誤:
ArgumentNullException was unhandled by user code
Value cannot be null.
Parameter name: query
在 DictionaryRepository 類中的以下行調用.AsTableServiceQuery()時出現錯誤:
var q = this.Context.QueryableEntities.Where(x => x.PartitionKey == Dictionary.ToString() && x.RowKey == word).AsTableServiceQuery();
您沒有提到您遇到的錯誤,但由於QueryableEntities
是只讀屬性,請嘗試使用mock.SetupGet
而不是mock.Setup
。
編輯:
進一步研究它的問題是.AsTableServiceQuery()
擴展方法嘗試將IQueryable<T>
轉換為DataServiceQuery<T>
,該方法失敗導致空異常。
Frederic Boerr 發表了一篇關於如何使用表存儲進行單元測試的帖子,應該可以幫助您解決問題。 Windows Azure 存儲:TDD 和模擬
我知道你特別問了如何使用 Moq 做到這一點,我沒有答案,但我想出了如何使用 Fakes 做類似的事情。
http://azurator.blogspot.com/2013/07/unit-testing-azure-table-storage-queries.html
本質上,您可以在CloudTableQuery<T>
上創建一個 Shim,它讀取查詢正在使用的Expression
對象,並使用如下代碼將相同的邏輯應用於您的 IEnumerable:
[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;
};
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.