В поисках лучшей реализации для этого модульного теста
Я использую xUnit и FluentAssertions для написания своих модульных тестов, и я застрял в следующей проблеме. Поскольку я не реализовал catch
(в GetCountriesAsync
) из 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.