async-await - это просто ключевые слова, которые говорят компилятору компилировать ваш код как реализацию IAsyncStateMachine
, а также ждут его завершения, оба эти слова должны использоваться совместно, чтобы они работали, и они работают только Task
объекты. Task
представляет часть работы, которая происходит.
Вы должны пометить свой метод SendEmail
как async
, изменить тип возвращаемого значения на Task
и await
свой вызов emailHandler.SendEmail
.
В итоге, если вы идете async
, то вы должны пройти async
до вверх и await
в некоторых или многих точках, в противном случае начните смотреть на синхронный запуск асинхронного кода, который как бы стреляет в себя.
public static async Task
Как всегда, Стивен Клири является отличным источником для async
знаний.
Most testing frameworks now support some sort of data based testing to let you run the same test on multiple data sets.
See the ValuesAttribute in NUnit.
xUnit.net, MBUnit and others have similar methods.
Обычно я создаю много разных тестов и даю каждому свое имя. Например, предположим, что есть 3 разных регулярных выражения {A, B и C} для сопоставления адреса электронной почты. Функция проверяет входящее письмо на совпадение и принимает первое найденное совпадение.
я бы следующие тесты.
Вообще-то я бы поставил один утверждают в каждом тест.
Иногда, однако, я помещаю более одного утверждения в тест , если все утверждения проверяют разные части одного и того же. Например, скажем, у меня есть функция, которая находит все электронные письма, соответствующие шаблону A. Мои тестовые каналы в списке писем, но только одно соответствует шаблону A. Функция возвращает список, и я ожидаю, что этот список будет содержать только один элемент в Это. Итак, я хотел бы заявить две вещи:
Я не думаю, что вам следует писать отдельный тест для каждого случая, поскольку все случаи связаны с одним и тем же: проверкой того, является ли строка правильным адресом электронной почты. Если вы используете MbUnit или NUnit для запуска тестов, вы можете использовать атрибуты RowTest и Row для передачи в тест различных значений. Другой способ - сохранить все различные форматы электронной почты в массиве и выполнить цикл по массиву и выполнить утверждение.
Если разные заклинания действительно сводятся к одному и тому же, это не проблема.
Однако, если один из адресов электронной почты внезапно нарушит проверку, вам придется отладка, чтобы выяснить, в каком случае произошла ошибка. Так что это кажется хорошей причиной, чтобы их разбить.
В итоге вы получите миллионы модульных тестов, что верно, поскольку они, в конце концов, тестируют модуль вашего приложения, но на практике несколько утверждений будут делать, если так в котором неудачное утверждение нарушает тест, не искажает смысла ошибки.
Если вы тестируете одни и те же функции, я бы проверил их в одном тесте с несколькими утверждениями, при условии, что ваши тесты остаются достаточно простыми.
Некоторые люди выступают за то, чтобы каждый тест должен был иметь только одно утверждение, потому что тест должен быть очень, очень и очень простым.
Если тест непростой, скажем, что у вас есть циклы и «если», вам понадобится тест для самого теста, чтобы проверить правильность его логики, и это нехорошо.
Если ваш тест имеет несколько утверждений, но по-прежнему остаются простыми (без циклов, без «если») и несколько утверждений проверяют одно и то же, тогда я бы не был столь агрессивным , защищая «одно утверждение на тест ». Выбор за вами.
Как упоминал @Paul, несколько тестовых сред поддерживают RowTests. Используя эту возможность, вы можете написать что-нибудь столь же чудовищное, как это:
[TestCase ("test@test.com", true)]
[TestCase ("x!x@test.com", true)]
[TestCase ("x#x@test.com", true)]
[TestCase ("x$x@test.com", true)]
[TestCase ("x%x@test.com", true)]
[TestCase ("x&x@test.com", true)]
[TestCase ("x'x@test.com", true)]
[TestCase ("x*x@test.com", true)]
[TestCase ("x+x@test.com", true)]
[TestCase ("x-x@test.com", true)]
[TestCase ("x/x@test.com", true)]
[TestCase ("x=x@test.com", true)]
[TestCase ("x?x@test.com", true)]
[TestCase ("x^x@test.com", true)]
[TestCase ("x_x@test.com", true)]
[TestCase ("x`x@test.com", true)]
[TestCase ("x{x@test.com", true)]
[TestCase ("x{x@test.com", true)]
[TestCase ("x|x@test.com", true)]
[TestCase ("x}x@test.com", true)]
[TestCase ("x~x@test.com", true)]
[TestCase ("test", false)]
[TestCase ("", false)]
[TestCase (null, false)]
public void IsEmail_Should_Match_Valid_Email_Addresses(string target, bool result)
{
Assert.AreEqual(result, target.IsEmail());
}
Или вы можете сделать то же самое с кучей утверждений. Обычно после выполнения некоторого действия объекту присваивается несколько свойств. Я думаю, что приведенное выше решение более читабельно.
Фреймворки BDD и / или контекста / спецификации , такие как SubSpec, у которого есть несколько ярких примеров , управляют этим, обрабатывая каждый пакет связанных утверждений как отдельный блок наблюдения, которому дается имя или описательная метка.
Ключевые элементы хорошего теста, к которому это подталкивает:
Тесты строк могут быть подходящими в некоторых случаях, когда вы действительно выполняете простой набор таблиц или матриц. вещи.
Также PropertyData xUnit.net может быть мощным и подходящим в некоторых случаях в качестве способа выполнения некоторых трюков в других ответах.