Дерево выражений не может содержать вызов или вызов, использующий необязательные аргументы
Вы пытаетесь «вызвать» метод ScanAsync для еще не настроенного GetContext ().Чтобы решить эту проблему, вам нужно установить возвращаемое значение для GetContext (), прежде чем пытаться настроить ScanAsync ()
Этот код очень сложно протестировать, поэтому давайте проведем его рефакторинг.
У вас естьизменить прямые вызовы _clientAccessor.GetContext()
на внедрение IDynamoDBContext.DynamoDbClientInitialization не имеет смысла, так как может быть легко заменен на IAmazonDynamoDb.Чтобы избавиться от подробных строк кода чтения конфигурации, используйте
services.AddAWSService<IAmazonDynamoDB>();
Все вызовы DynamoDb должны быть заключены в отдельный класс, называемый, например, DynamoDbManager
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);
}
}
Теперь ваш контроллер будет изменен таким образом ValuesController
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();
}
}
Рефакторинг завершен, начните писать модульные тесты ValuesControllerTests
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));
}
}
Вот и все, я провел два теста для каждого действия контроллера, потому что он гораздо более понятен - если вам действительно нужен только один тест, вы можете легко присоединиться к ним