XUnit Асинхронный тест не работает должным образом
Мы используем xUnit Framework в нашем проекте в качестве тестовой платформы с самого начала. В настоящее время в проекте есть 2200+ единичных тестов, и все кажется прекрасным.
Но вчера я решил запустить модульные тесты в сборках CI и ночных сборках. Борьба с контроллером сборной команды для запуска тестов xunit в течение 1-2 часов мне удастся запустить тесты. Но была проблема, там было 22 предупреждения о тестах, как показано ниже,
- Xunit.Sdk.EqualException: Assert.Equal() Ошибка
или
- System.ArgumentNullException: значение не может быть нулевым.
После нескольких исследований я понял, что эти тесты должны быть провалены, но кажется, что они прошли, потому что все эти тесты отмечены ключевым словом "async".
На самом деле не должно быть никаких ошибок, поскольку xUnit поддерживает асинхронные тесты в отношении этих сообщений
http://bradwilson.typepad.com/blog/2012/01/xunit19.html
http://sravi-kiran.blogspot.com.tr/2012/11/UnitTestingAsynchronousMethodsUsingMSTestAndXUnit.html
Для меня реальность Хаувервер - более легкая разница. Да xUnit работает без каких-либо проблем, но не тестируется должным образом.
Вот два небольших метода.
public async Task<string> AsyncTestMethod() {
throw new Exception("Test");
}
public string NormalTestMethod() {
throw new Exception("Test");
}
Как вы видите только разницу, первый метод, определяемый как "асинхронный",
И вот два теста для этих методов.
[Fact]
public async void XunitTestMethod_Async() {
Program p = new Program();
string result = await p.AsyncTestMethod();
Assert.Equal("Ok", result);
}
[Fact]
public void XunitTestMethod_Normal() {
Program p = new Program();
string result = p.NormalTestMethod();
Assert.Equal("Ok", result);
}
Оба из исходных методов вызывают исключение, поэтому я думаю, что оба теста должны потерпеть неудачу, но результат будет иным. Вы можете увидеть результаты:
![Test results]()
XunitTestMethod_Async проходит тест, но XunitTestMethod_Normal терпит неудачу.
Выбрасывание исключения не так, вы можете изменить содержание метода, которое вы хотите всегда передавать AsyncTestMethod.
Вот пример решения: https://github.com/bahadirarslan/AsyncTestWithxUnit
Я мог бы неправильно понимать или думать неправильно, но теперь это поведение вызывает много боли для меня
Надеюсь, ты можешь рассказать мне.
PS: Я создал проблему на странице xUnit github, но я не мог быть уверен, что это вызвано мной или xUnit. Поэтому я решил спросить здесь тоже.
Проблема: https://github.com/xunit/xunit/issues/96
Ответы
Ответ 1
Проблема заключается в том, что метод async void
не возвращает объект Task
, который xUnit мог бы изучить для исключений. xUnit не может даже отслеживать завершение конкретного метода async void
, в отличие от метода async Task
.
Кроме того, методы async void
не генерируют исключения в одном стеке стека даже для исключений, выведенных из синхронной части метода. Скорее, исключения распространяются на текущий контекст синхронизации через SynchronizationContext.Post
(в случае SynchronizationContext.Current != null
) или иначе через ThreadPool.QueueUserWorkItem
. Это поведение отличается от методов async Task
, более подробной информации. Можно отслеживать общее количество ожидающих методов async void
(через SynchronizationContext.OperationStarted
/OperationCompleted
), но не отдельные методы.
Итак, изменение сигнатуры метода XunitTestMethod_Async
от async void
до async Task
должно решить проблему.