В поисках лучшей реализации для этого модульного теста

Я использую xUnit и FluentAssertions для написания своих модульных тестов, и я застрял в следующей проблеме. Поскольку я не реализовал catchGetCountriesAsync) из WebException все же, я бросаю новый NotImplementedException в этом месте.

Этот код - единственный способ, которым я заставил тест действительно работать как ожидалось. Я также добавил нативную реализацию xUnit, поскольку FluentAssertions - это просто синтаксический сахар.

[Fact]
public async Task GetCountriesAsyncThrowsExceptionWithoutInternetConnection()
{
    // Arrange
    Helpers.Disconnect(); // simulates network disconnect
    var provider = new CountryProvider();

    try
    {
        // Act
        var countries = await provider.GetCountriesAsync();
    }
    catch (Exception e)
    {
        // Assert FluentAssertions
        e.Should().BeOfType<NotImplementedException>();

        // Assert XUnit
        Assert.IsType<NotImplementedException>(e);
    }
}

Хотя я нашел эту реализацию намного приятнее, она просто не работает.

[Fact]
public async Task GetCountriesAsyncThrowsExceptionWithoutInternetConnection3()
{
    // Arrange
    Helpers.Disconnect(); // simulates network disconnect
    var provider = new CountryProvider();

    // Act / Assert FluentAssertions
    provider.Invoking(async p => await p.GetCountriesAsync())
            .ShouldThrow<NotImplementedException>();

    // Act / Assert XUnit
    Assert.Throws<NotImplementedException>(async () => await provider.GetCountriesAsync());
}

Как VS2012/ReSharper уже предлагает убрать лишнее async Ключевое слово метода испытаний, я заменил async Task с void и тест все еще ведет себя так же, поэтому я подозреваю, что асинхронный ActionИх нельзя ждать, они скорее уволены и забыты.

Есть ли способ правильно реализовать это с помощью xUnit/FluentAssertions? Я думаю, что я должен пойти с моей первой реализацией, так как я не вижу никакой функциональности, как InvokingAsync(),

2 ответа

Решение

На самом деле, FA 2.0 имеет особую поддержку для обработки асинхронных исключений. Просто посмотрите на модульные тесты в AsyncFunctionExceptionAssertionSpecs. для различных примеров.

Что касается FluentAssertions, я добавил следующее в мой код:

using System;
using System.Threading.Tasks;

namespace FluentAssertions
{
    public static class FluentInvocationAssertionExtensions
    {
        public static Func<Task> Awaiting<T>(this T subject, Func<T, Task> action)
        {
            return () => action(subject);
        }
    }
}

и теперь вы можете сделать:

_testee.Awaiting(async x => await x.Wait<Foo>(TimeSpan.Zero))
        .ShouldThrow<BarException>();

в то время как _teste.Wait<T> возвращает Task<T>, Также наименование метода Awaiting имеет смысл, поскольку чистый вызов метода не приведет к тому, что вызывающая сторона поймает исключение, для этого нужно использовать await.

Другие вопросы по тегам