繁体   English   中英

Xunit - 如何使用异步任务和反射测试方法

[英]Xunit - How to test a method with async task and reflection

我尝试编写一个基本的单元测试类来测试我的 api 控制器。 但是,我似乎对 IDisposable 有问题,因为我收到以下错误:

无法访问已处置的对象。 此错误的一个常见原因是处理从依赖注入解析的上下文,然后尝试在应用程序的其他地方使用相同的上下文实例。 如果您在上下文上调用 Dispose() 或将上下文包装在 using 语句中,则可能会发生这种情况。 如果你使用依赖注入,你应该让依赖注入容器来处理上下文实例。

要测试的 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);
}

带有测试方法的类:

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);
    }
}

我通过使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM