C# Xunit-如何使用异步任务和反射测试方法
我尝试编写一个基本单元测试类来测试我的api控制器。但是,我似乎对IDisposable有问题,因为我得到以下错误: 无法访问已释放的对象。此错误的一个常见原因是处理通过依赖项注入解析的上下文,然后在应用程序的其他位置尝试使用相同的上下文实例。如果对上下文调用Dispose(),或将上下文包装到using语句中,则可能会发生这种情况。如果您使用的是依赖项注入,那么应该让依赖项注入容器处理上下文实例 待测试的API方法:C# Xunit-如何使用异步任务和反射测试方法,c#,reflection,.net-core,xunit,C#,Reflection,.net Core,Xunit,我尝试编写一个基本单元测试类来测试我的api控制器。但是,我似乎对IDisposable有问题,因为我得到以下错误: 无法访问已释放的对象。此错误的一个常见原因是处理通过依赖项注入解析的上下文,然后在应用程序的其他位置尝试使用相同的上下文实例。如果对上下文调用Dispose(),或将上下文包装到using语句中,则可能会发生这种情况。如果您使用的是依赖项注入,那么应该让依赖项注入容器处理上下文实例 待测试的API方法: [HttpGet("{id}")] virtual public async
[HttpGet("{id}")]
virtual public async Task<IActionResult> GetById(long id)
{
var type = typeof(TManager);
ConstructorInfo? constructorInfo = type.GetConstructor(new[] { typeof(ApiDbContext), typeof(IMapper) });
if (constructorInfo == null)
return BadRequest();
object classObject = constructorInfo.Invoke(new object[] { dbContext, mapper });
MethodInfo? methodInfo = type.GetMethod("GetByIdDto");
if (methodInfo == null)
return BadRequest();
var task = Task.Run(() => methodInfo.Invoke(classObject, new object[] { id }));
TEntityDTO entity = (TEntityDTO)await task.ConfigureAwait(false);
if (entity == null)
{
return NotFound("Record couldn't be found.");
}
return Ok(entity);
}
[HttpGet(“{id}”)]
虚拟公共异步任务GetById(长id)
{
var type=typeof(TManager);
ConstructorInfo?ConstructorInfo=type.GetConstructor(新[]{typeof(ApiDbContext),typeof(IMapper)});
if(constructorInfo==null)
返回请求();
object classObject=constructorInfo.Invoke(新对象[]{dbContext,mapper});
MethodInfo?MethodInfo=type.GetMethod(“GetByIdDto”);
if(methodInfo==null)
返回请求();
var task=task.Run(()=>methodInfo.Invoke(classObject,新对象[]{id}));
TEntityDTO实体=(TEntityDTO)等待任务。配置等待(false);
if(实体==null)
{
returnnotfound(“找不到记录”);
}
返回Ok(实体);
}
使用测试方法进行分类:
public abstract class BaseControllerUnitTests<TController, TEntity, TEntityDTO> : IDisposable where TController : class
{
protected IMapper Mapper { get; set; }
protected ApiDbContext Context { get; set; }
protected BaseControllerUnitTests()
{
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
Context.Dispose();
}
// free native resources
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
[Fact]
public async Task TestGetItemIdNotFound()
{
// Arrange
long id = 99;
var type = typeof(TController);
ConstructorInfo constructorInfo = type.GetConstructor(new[] { typeof(ApiDbContext), typeof(IMapper) });
Assert.NotNull(constructorInfo);
object classObject = constructorInfo.Invoke(new object[] { Context, Mapper });
MethodInfo methodInfo = type.GetMethod("GetById");
Assert.NotNull(methodInfo);
// Act
var task = Task.Run(() => methodInfo.Invoke(classObject, new object[] { id }));
var controllerResponse = await task.ConfigureAwait(false);
// Assert
Assert.IsType<NotFoundObjectResult>(controllerResponse);
var objectResponse = controllerResponse as ObjectResult;
Assert.Equal(404, objectResponse.StatusCode);
}
}
公共抽象类BaseControllerUnitTests:IDisposable,其中TController:class
{
受保护的IMapper映射程序{get;set;}
受保护的ApiDbContext上下文{get;set;}
受保护的BaseControllerUnitTests()
{
}
受保护的虚拟void Dispose(bool disposing)
{
如果(处置)
{
//处置托管资源
Context.Dispose();
}
//免费本地资源
}
公共空间处置()
{
处置(真实);
总干事(本);
}
[事实]
公共异步任务TestGetItemIdNotFound()
{
//安排
长id=99;
变量类型=类型(t控制器);
ConstructorInfo ConstructorInfo=type.GetConstructor(新[]{typeof(ApiDbContext),typeof(IMapper)});
Assert.NotNull(constructorInfo);
object classObject=constructorInfo.Invoke(新对象[]{Context,Mapper});
MethodInfo MethodInfo=type.GetMethod(“GetById”);
Assert.NotNull(methodInfo);
//表演
var task=task.Run(()=>methodInfo.Invoke(classObject,新对象[]{id}));
var controllerResponse=await task.ConfigureAwait(false);
//断言
IsType(controllerResponse);
var objectResponse=controllerResponse作为ObjectResult;
Assert.Equal(404,objectResponse.StatusCode);
}
}
我通过使用dynamic
[Fact]
public async Task TestGetItemIdNotFound()
{
// Arrange
long id = 99;
var type = typeof(TController);
ConstructorInfo constructorInfo = type.GetConstructor(new[] { typeof(ApiDbContext), typeof(IMapper) });
Assert.NotNull(constructorInfo);
object classObject = constructorInfo.Invoke(new object[] { Context, Mapper });
MethodInfo methodInfo = type.GetMethod("GetById");
Assert.NotNull(methodInfo);
// Act
dynamic task = methodInfo.Invoke(classObject, new object[] { id });
var controllerResponse = await task.ConfigureAwait(false);
// Assert
Assert.IsType<NotFoundObjectResult>(controllerResponse);
var objectResponse = controllerResponse as ObjectResult;
Assert.Equal(404, objectResponse.StatusCode);
}
[事实]
公共异步任务TestGetItemIdNotFound()
{
//安排
长id=99;
变量类型=类型(t控制器);
ConstructorInfo ConstructorInfo=type.GetConstructor(新[]{typeof(ApiDbContext),typeof(IMapper)});
Assert.NotNull(constructorInfo);
object classObject=constructorInfo.Invoke(新对象[]{Context,Mapper});
MethodInfo MethodInfo=type.GetMethod(“GetById”);
Assert.NotNull(methodInfo);
//表演
动态任务=methodInfo.Invoke(类对象,新对象[]{id});
var controllerResponse=await task.ConfigureAwait(false);
//断言
IsType(controllerResponse);
var objectResponse=controllerResponse作为ObjectResult;
Assert.Equal(404,objectResponse.StatusCode);
}