【发布时间】:2018-02-13 09:39:21
【问题描述】:
我正在为基于 Azure 表存储的持久性组件实施单元测试。该项目有多个 Table Storage 持久化组件,因此目前这些组件实现了一个抽象的TableStorageBase 类来共享它们之间的公共代码。
假设我们有一个类 FooTableStorageComponent 正在测试中,它从表存储中检索 Foo,如果它已过期(即时间戳超过 7 天),它会创建一个新的 Foo。我想创建一个表存储存根,它总是给FooTableStorageComponent 一个虚拟的Foo 7 天以上。然后我想创建一个单元测试,检查是否因此创建了一个新的Foo。不幸的是,由于抽象的TableStorageBase 类,我不能假装连接到 Azure。
如何重新设计此结构以使其可进行单元测试?我应该如何对我的FooTableStorageComponent 进行单元测试?
抽象 TableStorageBase 类:
public abstract class TableStorageBase
{
private readonly string tableName;
protected readonly CloudStorageAccount storageAccount;
protected TableRequestOptions DefaultTableRequestOptions { get; }
protected OperationContext DefaultOperationContext { get; }
public CloudTable Table
{
get
{
return storageAccount.CreateCloudTableClient().GetTableReference(tableName);
}
}
public TableStorageBase(
string connectionString,
string tableName,
LocationMode consistency)
{
this.tableName = tableName;
storageAccount = CloudStorageAccount.Parse(connectionString);
ServicePoint tableServicePoint =
ServicePointManager.FindServicePoint(storageAccount.TableEndpoint);
tableServicePoint.UseNagleAlgorithm = false;
tableServicePoint.ConnectionLimit = 500;
DefaultTableRequestOptions = new TableRequestOptions()
{
PayloadFormat = TablePayloadFormat.JsonNoMetadata,
MaximumExecutionTime = TimeSpan.FromSeconds(5),
RetryPolicy = new LinearRetry(TimeSpan.FromMilliseconds(500), 3),
LocationMode = consistency
};
DefaultOperationContext = new OperationContext();
Table.CreateIfNotExists(DefaultTableRequestOptions, DefaultOperationContext);
}
}
待测类:
public class FooTableStorageComponent : TableStorageBase, IFooComponent
{
private const string TableName = "foo";
private const LocationMode ConsistencyMode = LocationMode.PrimaryOnly;
public FooTableStorageComponent(string connectionString)
: base(connectionString, TableName, ConsistencyMode)
{
}
public GetFoo(string partitionKey, string rowKey)
{
var retrieveOperation = TableOperation.Retrieve<FooTableEntity>(partitionKey, rowkey)
var tableEntity = (await Table.ExecuteAsync(
retrieveOperation,
DefaultTableRequestOptions,
DefaultOperationContext)).Result as FooTableEntity;
if (tableEntity != null && tableEntity.Timestamp > DateTime.Now.AddDays(-7))
{
return tableEntity.ToEntity();
}
else
{
var foo = CreateFoo(partitionKey, rowKey)
var insertOperation = TableOperation.InsertOrMerge(FooTableEntity.From(foo));
await Table.ExecuteAsync(insertOperation);
return foo;
}
}
}
【问题讨论】:
标签: c# unit-testing azure mocking azure-table-storage