C# 使用Xunit进行.Net核心测试
这是我第一次编写测试用例,我并没有陷入困境,也不知道如何继续下去 我有以下API。在下面的示例中,我有两个端点要执行测试C# 使用Xunit进行.Net核心测试,c#,asp.net-core,moq,xunit,xunit.net,C#,Asp.net Core,Moq,Xunit,Xunit.net,这是我第一次编写测试用例,我并没有陷入困境,也不知道如何继续下去 我有以下API。在下面的示例中,我有两个端点要执行测试 public class ValuesController : Controller { //This interface is used to setup dynamo db and connection to aws private IDynamoDbClientInitialization _clientAccessor; private sta
public class ValuesController : Controller
{
//This interface is used to setup dynamo db and connection to aws
private IDynamoDbClientInitialization _clientAccessor;
private static string dynamoDbTable = string.Empty;
public ValuesController(IOptions<Dictionary<string, string>> appSettings, IDynamoDbClientInitialization clientAccessor)
{
var vals = appSettings.Value;
dynamoDbTable = vals["dynamoDbTable"];
_clientAccessor = clientAccessor;
}
[HttpGet("api/data")]
public async Task<List<MyModel>> GetAllData(string type, string status)
{
List<ScanCondition> conditions = new List<ScanCondition>();
conditions.Add(new ScanCondition("Type", ScanOperator.Equal, type));
conditions.Add(new ScanCondition("Status", ScanOperator.Equal, status));
var response = await _clientAccessor.GetContext().ScanAsync<MyModel>(conditions, AWSHelperMethods.GetDynamoDbOperationConfig(dynamoDbTable)).GetRemainingAsync();
return results.Select(x => x.UpdatedBy.ToLower()).ToList();
}
[HttpPost("api/save")]
public async Task<IActionResult> SaveData([FromBody] List<MyModel> listData, string input, string name, string type)
{
List<MyModel> model = null;
foreach (var data in listData)
{
//populating data here
await _clientAccessor.GetContext().SaveAsync(data, AWSHelperMethods.GetDynamoDbOperationConfig(dynamoDbTable));
}
return Ok();
}
}
public class DynamoDbClientInitialization : IDynamoDbClientInitialization
{
private readonly DynamoDbClientSettings settings;
private DynamoDBContext _awsContext;
public DynamoDbClientInitialization(IOptions<DynamoDbClientSettings> options)
{
settings = options?.Value;
}
public DynamoDBContext GetContext()
{
//Check is context already exists. If not create a new one.
if(_awsContext != null)
{
return _awsContext;
}
else
{
var creds = AWSHelperMethods.SetAwsCredentials(settings.Id, settings.Password);
var dynamoClient = AWSHelperMethods.GetDynamoDbClient(creds, settings.Region);
_awsContext = AWSHelperMethods.GetDynamoDbContext(dynamoClient);
return _awsContext;
}
}
}
public static class AWSHelperMethods
{
public static BasicAWSCredentials SetAwsCredentials(string awsId, string awsPassword)
{
var creds = new BasicAWSCredentials(awsId, awsPassword);
return creds;
}
public static AmazonDynamoDBClient GetDynamoDbClient(BasicAWSCredentials creds, RegionEndpoint awsDynamoDbRegion)
{
var client = new AmazonDynamoDBClient(creds, awsDynamoDbRegion);
return client;
}
public static DynamoDBContext GetDynamoDbContext(AmazonDynamoDBClient client)
{
var context = new DynamoDBContext(client);
return context;
}
public static DynamoDBOperationConfig GetDynamoDbOperationConfig(string dynamoDbTable)
{
DynamoDBOperationConfig config = new DynamoDBOperationConfig() { OverrideTableName = dynamoDbTable };
return config;
}
}
公共类值控制器:控制器
{
//此接口用于设置dynamo db和与aws的连接
私人Idynamodb客户化接受者;
私有静态字符串dynamoDbTable=string.Empty;
公共价值控制器(IOPS应用程序设置、IDynamodb客户化客户端接受器)
{
var vals=appSettings.Value;
dynamoDbTable=vals[“dynamoDbTable”];
_clientAccessor=clientAccessor;
}
[HttpGet(“api/数据”)]
公共异步任务GetAllData(字符串类型、字符串状态)
{
列表条件=新列表();
添加(新的ScanCondition(“Type”,ScanOperator.Equal,Type));
添加(新的扫描条件(“状态”,ScanOperator.Equal,Status));
var response=await_clientAccessor.GetContext().ScanAsync(条件,AWSHelperMethods.getdynamodbooperationconfig(dynamoDbTable)).GetRemainingAsync();
返回结果。选择(x=>x.UpdatedBy.ToLower()).ToList();
}
[HttpPost(“api/save”)]
公共异步任务SaveData([FromBody]列表listData,字符串输入,字符串名称,字符串类型)
{
列表模型=null;
foreach(listData中的var数据)
{
//在这里填充数据
wait_clientAccessor.GetContext().SaveAsync(数据,AWSHelperMethods.getdynamodboOperationConfig(dynamoDbTable));
}
返回Ok();
}
}
公共类动态客户化:IDynamodb客户化
{
专用只读DynamoDbClientSettings设置;
专用DynamoDBContext\u awsContext;
公共发电机客户化(IOPS选项)
{
设置=选项?.Value;
}
公共DynamoDBContext GetContext()
{
//检查上下文是否已存在。如果不存在,请创建一个新上下文。
如果(_awsContext!=null)
{
返回awsContext;
}
其他的
{
var creds=AWSHelperMethods.SetAwsCredentials(settings.Id、settings.Password);
var dynamoClient=AWSHelperMethods.GetDynamoDbClient(creds,settings.Region);
_awsContext=AWSHelperMethods.GetDynamoDbContext(dynamoClient);
返回awsContext;
}
}
}
公共静态类AWSHelperMethods
{
公共静态基本WSCredentials设置AWSCredentials(字符串awsId、字符串awsPassword)
{
var creds=新的基本凭证(awsId、awsPassword);
回信;
}
公共静态AmazondynamodClient GetDynamoDbClient(基本凭证凭证凭证凭证、区域点AWSDynamodRegion)
{
var client=新的AmazondynamodClient(creds,AWSDynamodRegion);
返回客户;
}
公共静态DynamoDBContext GetDynamoDbContext(AmazonDynamoDBClient客户端)
{
var context=新的DynamoDBContext(客户端);
返回上下文;
}
公共静态dynamodbooperationconfig getdynamodbooperationconfig(字符串dynamoDbTable)
{
dynamodbooperationconfig=new dynamodbooperationconfig(){OverrideTableName=dynamoDbTable};
返回配置;
}
}
下面是我添加的xunit项目。在这里,我使用MOQ来MOQ我的aws连接和其他连接。以下是针对该准则的评论中的问题
public class DataTest
{
[Fact]
public void PassingTest()
{
//Arrange
var dynamoDbTable = "someValue";
//Trying to moq IOptions
var moqOp = new Mock<IOptions<Dictionary<string, string>>>();
//Create an instance to hold desired values
var vals = new Dictionary<string, string>();
//Set expected value
vals["dynamoDbTable"] = dynamoDbTable;
//Setup dependency behavior
moqOp.Setup(_ => _.Value).Returns(vals);
//Trying to moq my connection
var moqDb = new Mock<IDynamoDbClientInitialization>();
//Fake data
List<MyModel> data = new List<MyModel>()
{
//populate as needed
};
moqDb
.Setup(_ => _.GetContext().ScanAsync<MyModel>
(It.IsAny<List<ScanCondition>>(), AWSHelperMethods.GetDynamoDbOperationConfig(dynamoDbTable)).GetRemainingAsync())
.ReturnsAsync(data);
ValuesController controller = new ValuesController(moqOp.Object,
moqDb.Object);
var actual = controller.GetAllData();
}
}
公共类数据测试
{
[事实]
public void PassingTest()
{
//安排
var dynamoDbTable=“someValue”;
//试着减少吸烟
var moqOp=new Mock();
//创建一个实例来保存所需的值
var vals=新字典();
//设置期望值
VAL[“发电机表”]=发电机表;
//设置依赖行为
moqOp.Setup(=>qop.Value).Returns(VAL);
//正在尝试删除我的连接
var moqDb=new Mock();
//假数据
列表数据=新列表()
{
//根据需要填充
};
moqDb
.Setup(=>\u0.GetContext().ScanAsync
(It.IsAny(),AWSHelperMethods.getdynamodboOperationConfig(dynamoDbTable)).GetRemainingAsync())
.ReturnsAsync(数据);
ValuesController=新的ValuesController(moqOp.Object,
moqDb.对象);
var actual=controller.GetAllData();
}
}
上面我得到的错误如下:
表达式树不能包含使用可选参数的调用或调用
这是在线的
.Setup(_ => _.GetContext().ScanAsync<MyModel>
(It.IsAny<List<ScanCondition>>(), AWSHelperMethods.GetDynamoDbOperationConfig(dynamoDbTable)).GetRemainingAsync())
.Setup(\u=>\ uu.GetContext().ScanAsync
(It.IsAny(),AWSHelperMethods.getdynamodboOperationConfig(dynamoDbTable)).GetRemainingAsync())
有人能帮忙解决吗
---更新---
公共接口IDynamoDbManager
{
任务GetAsync(IEnumerable条件);
任务SaveAsync(T项);
}
表达式树不能包含使用
可选参数
您正在尝试“调用”尚未设置GetContext()的上的ScanAsync方法。要解决此问题,必须在尝试设置ScanAsync()之前为GetContext()设置返回值
这段代码很难测试,所以让我们重构它 您必须将对
\u clientAccessor.GetContext()
的直接调用更改为对IDynamoDBContext的注入。
dynamodb客户化没有意义,因为可以很容易地用IAmazonDynamoDb替代。要消除冗长的配置读取代码行,请使用
services.AddAWSService<IAmazonDynamoDB>();
services.AddAWSService();
对DynamoDb的所有调用都应该封装在一个单独的类中,该类称为,DynamoDbManager
公共类DynamoDbManager:DynamoDBContext,IDynamoDbManager其中T:class
{
专用dynamodbooperationconfig _config;
公共DynamoDbManager(IAmazonDynamoDB客户端,字符串ta)
services.AddAWSService<IAmazonDynamoDB>();
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));
}
}