[英]Xunit - How to test a method with async task and reflection
I try to write a base unit-test class for testing my api-controller.我尝试编写一个基本的单元测试类来测试我的 api 控制器。 However, I seem to have a problem with IDisposable, because I get the following error:
但是,我似乎对 IDisposable 有问题,因为我收到以下错误:
Cannot access a disposed object.
无法访问已处置的对象。 A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application.
此错误的一个常见原因是处理从依赖注入解析的上下文,然后尝试在应用程序的其他地方使用相同的上下文实例。 This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement.
如果您在上下文上调用 Dispose() 或将上下文包装在 using 语句中,则可能会发生这种情况。 If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
如果你使用依赖注入,你应该让依赖注入容器来处理上下文实例。
API-method to be tested:要测试的 API 方法:
[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);
}
Class with test method:带有测试方法的类:
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);
}
}
I found a solution by using dynamic
我通过使用
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.