Xunit - Как протестировать метод с помощью asyn c задачи и отражения - PullRequest
0 голосов
/ 07 января 2020

Я пытаюсь написать базовый класс модульного тестирования для тестирования моего 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);
}

Класс с методом test :

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

1 Ответ

0 голосов
/ 08 января 2020

Я нашел решение, используя 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...