表达式树可能不包含使用以下内容的调用或调用
可选参数
您正在尝试在尚未设置 GetContext() 的情况下“调用”方法 ScanAsync。要解决此问题,您必须在尝试设置 ScanAsync() 之前设置 GetContext() 的返回值
这段代码很难测试,所以让我们重构它。
您必须更改直接调用_clientAccessor.GetContext()
注入 IDynamoDBContext。
DynamoDbClientInitialization 没有意义,因为可以轻松替换为 IAmazonDynamoDb。要摆脱冗长的配置读取代码行,请使用
services.AddAWSService<IAmazonDynamoDB>();
对 DynamoDb 的所有调用都应封装在一个单独的类中,例如,Dynamo数据库管理器
public class DynamoDbManager<T> : DynamoDBContext, IDynamoDbManager<T> where T : class
{
private DynamoDBOperationConfig _config;
public DynamoDbManager(IAmazonDynamoDB client, string tableName): base(client)
{
_config = new DynamoDBOperationConfig()
{
OverrideTableName = tableName
};
}
public Task<List<T>> GetAsync(IEnumerable<ScanCondition> conditions)
{
return ScanAsync<T>(conditions, _config).GetRemainingAsync();
}
public Task SaveAsync(T item)
{
return base.SaveAsync(item, _config);
}
}
现在你的控制器将被这样改变值控制器
public class ValuesController : Controller
{
private readonly IDynamoDbManager<MyModel> _dynamoDbManager;
//This interface is used to setup dynamo db and connection to aws
private static string dynamoDbTable = string.Empty;
public ValuesController(IOptions<Dictionary<string, string>> appSettings, IDynamoDbManager<MyModel> dynamoDbManager)
{
_dynamoDbManager = dynamoDbManager;
var vals = appSettings.Value;
dynamoDbTable = vals["dynamoDbTable"];
}
[HttpGet("api/data")]
public async Task<IActionResult> GetAllData(string type, string status)
{
var conditions = new List<ScanCondition>
{
new ScanCondition("Type", ScanOperator.Equal, type),
new ScanCondition("Status", ScanOperator.Equal, status)
};
var result = await _dynamoDbManager.GetAsync(conditions);
var response = result.Select(_ => _.UpdatedBy.ToLower()).ToList();
return Ok(response);
}
[HttpPost("api/save")]
public async Task<IActionResult> SaveData([FromBody] List<MyModel> listData, string input, string name, string type)
{
foreach (var data in listData)
{
//populating data here
await _dynamoDbManager.SaveAsync(data);
}
return Ok();
}
}
重构完成,开始编写单元测试值控制器测试
public class ValuesControllerTests
{
private Mock<IDynamoDbManager<MyModel>> _dbManager;
private ValuesController _valuesController;
public ValuesControllerTests()
{
var mockRepository = new MockRepository(MockBehavior.Loose);
_dbManager = mockRepository.Create<IDynamoDbManager<MyModel>>();
var options = new OptionsWrapper<Dictionary<string, string>>(new Dictionary<string, string>()
{
{"dynamoDbTable", nameof(MyModel) }
});
_valuesController = new ValuesController(options, _dbManager.Object);
}
[Fact]
public async Task GetAllData_ShouldSelectUpdateByInLowerCase()
{
//
var searchResult = new List<MyModel>()
{
new MyModel() {UpdatedBy = "UpdatedBy1"}
};
_dbManager
.Setup(_ => _.GetAsync(It.Is<List<ScanCondition>>(list => list.Count == 2)))
.ReturnsAsync(searchResult);
//
var result = await _valuesController.GetAllData("typeValue", "statusValue");
//
var okResult = result as OkObjectResult;
Assert.NotNull(okResult);
var values = okResult.Value as List<string>;
Assert.Contains("updatedby1", values);
}
[Fact]
public async Task SaveData_ShouldCallSaveForAllRequestedData()
{
//
var listData = new List<MyModel>()
{
new MyModel(),
new MyModel(),
new MyModel()
};
_dbManager
.Setup(_ => _.SaveAsync(It.IsAny<MyModel>()))
.Returns(Task.CompletedTask);
//
var result = await _valuesController.SaveData(listData, "","", "");
//
_dbManager.Verify(_ => _.SaveAsync(It.IsAny<MyModel>()), Times.Exactly(3));
}
}
就这样,我对每个控制器操作做了两次测试,因为它更容易理解 - 如果您确实只需要一次测试,您可以轻松加入它们