2016-05-23 7 views
0

я не знаю, почему мои тесты блок не: Метод испытываемого:исключения XUnit терпит неудачу

public async Task<MyType> Get(string externalId) 
{ 
    if (externalId == null) 
     throw new ArgumentNullException(); 
    if (externalId == "" || externalId == " ") 
     throw new FormatException(); 
     // ... 
} 

испытания Единица измерения:

Action action = async() => await controller.Get(null); 

// Act & Assert 
action.ShouldThrow<ArgumentNullException>(); 

И есть не потому, что сообщение об ошибке говорит:

Ожидаемое исключение ArgumentNullException, которое не было выбрано, но не было выполнено исключение.

И это странно, потому что во время отладки этого теста была выбрана линия исключений!

Я использую xunit и fluentasserttions.

+0

Почему ваш блок тест содержит код лезвия? Я подозреваю, что вы скопировали и наклеили неправильную вещь. Пожалуйста, предоставьте [mcve]. –

+2

Вы не ожидаете действий, поэтому исключение не наблюдается, даже если оно происходит. Используйте Func вместо Action и ожидайте его, тогда будет наблюдаться исключение. –

+0

@MartinCostello спасибо. – Nerf

ответ

0

Эта линия проблема:

Action action = async() => await controller.Get(null); 

Это создает async void метод, который делает его чрезвычайно трудно наблюдать исключения (и, таким образом, сделать надлежащие испытания).

Last time I checked, Fluent утверждение поддерживает только стиль анти-паттерна «асинхронных» утверждений:

sut.Awaiting(…).ShouldThrow<T>(); 

К сожалению, это использует блокировку синхронизации поверх асинхронный хак, так что bound to fail при использовании одно- резьба SynchronizationContext. О, и догадаться which unit testing framework provides a single-threaded SynchronizationContext? Если вы догадались xUnit, вы получите приз.

Итак, «асинхронные» тесты FA не будут работать с xUnit из коробки. У вас есть несколько вариантов.

Вы можете избежать контекста xUnit, выполнив весь свой тест в потоке пула потоков; это неэффективно, но проделает свою работу:

await Task.Run(() => 
{ 
    controller.Awaiting(c => c.Get(null)).ShouldThrow<ArgumentNullException>(); 
}); 

Не совсем красиво.

В качестве альтернативы, вы можете использовать свои собственные асинхронные-совместимые утверждения, как the one I wrote:

await AsyncAssert.ThrowsAsync<ArgumentNullException>(() => controller.Get(null)); 
Смежные вопросы