Как проверить наличие ожидаемого исключения с конкретным сообщением об исключении из файла ресурсов в Visual Studio Test?

Visual Studio Test может проверять наличие ожидаемых исключений с помощью атрибута ExpectedException. Вы можете передать исключение следующим образом:

[TestMethod]
[ExpectedException(typeof(CriticalException))]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Вы также можете проверить сообщение, содержащееся в ExpectedException, например:

[TestMethod]
[ExpectedException(typeof(CriticalException), "An error occured")]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Но при тестировании приложений I18N я бы использовал файл ресурсов для получения этого сообщения об ошибке (любой может даже решить проверить различные локализации сообщения об ошибке, если я хочу, но Visual Studio не позволит мне сделать это:

[TestMethod]
[ExpectedException(typeof(CriticalException), MyRes.MultipleOrganisationsNotAllowed)]
public void GetOrganisation_MultipleOrganisations_ThrowsException()

Компилятор выдаст следующую ошибку:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute

Кто-нибудь знает, как проверить исключение, которое имеет сообщение из файла ресурсов?

Одним из вариантов, который я рассмотрел, является использование пользовательских классов исключений, но на основе часто встречающихся рекомендаций, таких как:

"Do create and throw custom exceptions if you have an error condition that can be programmatically handled in a different way than any other existing exception. Otherwise, throw one of the existing exceptions." Source

Я не собираюсь обрабатывать исключения по-разному в обычном потоке (это критическое исключение, поэтому я все равно перехожу в режим паники), и я не думаю, что создание исключения для каждого тестового случая - это правильная вещь. Есть мнения?

 Gareth D08 окт. 2009 г., 18:55
Параметр сообщения не проверяется на соответствие сообщению сгенерированного исключения.

Ответы на вопрос(7)

Аргумент Сообщение ExpectedException не совпадает с сообщением об исключении. Скорее это сообщение, которое печатается в результатах теста, если ожидаемое исключение фактически не произошло.

Я думаю, что вы можете просто сделать явную попытку в своем тестовом коде вместо того, чтобы полагаться на атрибут ExpectedException, чтобы сделать это за вас. Затем вы можете найти какой-нибудь вспомогательный метод, который будет читать файл ресурсов и сравнивать сообщение об ошибке с сообщением об ошибке, которое было перехвачено. (конечно, если не было исключения, тогда контрольный пример следует считать неудачным)

Интересно, NUnit движется по пути от простоты ... но вот, пожалуйста.

New enhancements (2.4.3 and up?) to the ExpectedException attribute allow you more control on the checks to be performed on the expected Exception via a Handler method, Подробнее оофициальная страница NUnit doc... ближе к концу страницы.

[ExpectedException( Handler="HandlerMethod" )]
public void TestMethod()
{
...
}

public void HandlerMethod( System.Exception ex )
{
...
}

Note: Something doesn't feel right here.. Why are your exceptions messages internationalized.. Are you using exceptions for things that need to be handled or notified to the user. Unless you have a bunch of culturally diverse developers fixing bugs.. you shouldn't be needing this. Exceptions in English or a common accepted language would suffice. But in case you have to have this.. its possible :)

 15 сент. 2014 г., 13:23
Я использую платформу NUnit версии 2.6, а атрибут [ExpectedException (Handler = & quot; HandlerMethod & quot;)] не компилируется
 16 сент. 2014 г., 12:55
@ Gishu компилятор жалуется на "неизвестный символ" так что он, кажется, не знает эту конкретную сигнатуру атрибута
 15 сент. 2014 г., 13:55
@mishrsud - я думаю, что компилятор предоставит вам более подробную информацию об этом. Проверьте панель вывода - на что она жалуется?
 17 сент. 2014 г., 12:16
@ mishrsud - пример прямо со страницы документации nunit v2.6.2nunit.org/index.php?p=exception&r=2.6.2 | Можете ли вы проверить, не забираете ли вы не ту версию сборки, есть ли необходимые с помощью stmts, очистить проект? Просто мысли вслух здесь ...
 22 сент. 2008 г., 14:37
Вы не думаете, что метод получения сообщения об ошибке в диалоговом окне исключения является хорошим дизайном? У меня сложилось впечатление, что это было обычным явлением, и оно упрощает код ошибки ... Я знаю, что не хочу видеть диалог на китайском языке!

Если вы переключитесь на использование очень приятноxUnit.Net тестируя библиотеку, вы можете заменить [ExpectedException] на что-то вроде этого:

[Fact]
public void TestException()
{
   Exception ex = Record.Exception(() => myClass.DoSomethingExceptional());
   // Assert whatever you like about the exception here.
}

Я бы рекомендовал использовать вспомогательный метод вместо атрибута. Что-то вроде этого:

public static class ExceptionAssert
{
  public static T Throws<T>(Action action) where T : Exception
  {
    try
    {
      action();
    }
    catch (T ex)
    {
      return ex;
    }
    Assert.Fail("Exception of type {0} should be thrown.", typeof(T));

    //  The compiler doesn't know that Assert.Fail
    //  will always throw an exception
    return null;
  }
}

Затем вы можете написать свой тест примерно так:

[TestMethod]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
{
  OrganizationList organizations = new Organizations();
  organizations.Add(new Organization());
  organizations.Add(new Organization());

  var ex = ExceptionAssert.Throws<CriticalException>(
              () => organizations.GetOrganization());
  Assert.AreEqual(MyRes.MultipleOrganisationsNotAllowed, ex.Message);
}

Это также имеет то преимущество, что он проверяет, что исключение выдается на строке, которую вы ожидали, что оно будет сгенерировано, а не где-либо в вашем тестовом методе.

 23 мар. 2012 г., 08:51
Какой ответ! Потрясающие. Это мне тоже помогло :)
 05 дек. 2013 г., 11:41
Отличное решение, которое сработало для меня.
 04 нояб. 2008 г., 13:32
путь !!! Мне нравится этот способ больше.

Я столкнулся с этим вопросом, пытаясь решить подобную проблему самостоятельно. (Я подробно опишу решение, на котором остановился ниже.)

Я должен согласиться с комментариями Гишу относительно интернационализации сообщений об исключениях, являющихся запахом кода.

Первоначально я сделал это в своем собственном проекте, чтобы обеспечить согласованность между сообщениями об ошибках, выдаваемыми моим приложением, и моими тестами. то есть, чтобы определять мои сообщения об исключениях только в одном месте, в то время файл Resource казался разумным местом для этого, поскольку я уже использовал его для различных меток и строк (и поскольку имел смысл добавить ссылку чтобы это в моем тестовом коде, чтобы убедиться, что те же самые метки показаны в соответствующих местах).

В какой-то момент я рассмотрел (и протестировал) использование блоков try / catch, чтобы избежать требования к константе атрибутом ExpectedException, но это выглядело так, как будто это привело бы к большому количеству дополнительного кода при применении в большом масштабе.

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

Мой тестовый код тогда просто сводится к (простите за искажение ...):

[Test, 
    ExpectedException(typeof(System.ArgumentException),
    ExpectedException=ProductExceptionMessages.DuplicateProductName)]
public void TestCreateDuplicateProduct()
{
    _repository.CreateProduct("TestCreateDuplicateProduct");
    _repository.CreateProduct("TestCreateDuplicateProduct");
} 
Решение Вопроса

Just мнение, но я бы сказал, текст ошибки:

is part of the test, in which case getting it from the resource would be 'wrong' (otherwise you could end up with a consistantly mangled resource), so just update the test when you change the resource (or the test fails) is not part of the test, and you should only care that it throws the exception.

Обратите внимание, что первый вариант должен позволять вам тестировать несколько языков, учитывая возможность запуска с локалью.

Что касается множественных исключений, то я с земли C ++, где допустимо (если не часто), но создание метаданных .Net допускает загрузку и загрузку исключений (с точностью до одного на оператор throw!) В больших heirachies. системе, вероятно, это не нравится, отсюда и этот совет.

 30 апр. 2012 г., 10:14
Я до сих пор этого не понимал. В этом случае я согласен
 29 апр. 2012 г., 16:34
Я не слежу, используя DataBound Unit test, вы можете оставить свой торт и съесть его тоже. сопоставьте ресурсы в привязке данных и сопоставьте свою культуру сообщений в тесте или наоборот. нет?
 30 апр. 2012 г., 02:33
@ Микки: Да, тыcan, но в моем исходном сообщении было указано, что вы в первую очередь не поймаете сообщения, определенные неправильно: моя позиция заключалась в том, что при тестировании вы проверяете результат по явным значениям, а не по тому, что должно давать тот же результат: для метода это делает2 + 2, вы проверяете это возвращает4не2 + 2, Если вас волнует, что это за сообщение, то я думаю, что вы должны четко проверить, дает ли оноright результат, а не толькоsame результат. Но не стесняйтесь делать вещи по-другому, если у вас есть причина!
 25 апр. 2012 г., 10:31
Я бы реализовал простой процесс, который читает файл ресурсов и находит сообщение для записи, ваш метод - отличный способ удалить карту и потерять драгоценное время на обновление тестов (чего мы больше всего стараемся избегать)
 26 апр. 2012 г., 00:54
@ Микки: Что ж, тебе повезло: другой ответ - это то, что ты ищешь! если тыspecifically хотетьunit-проверить, что он получает то же сообщение, что нормально, но я предпочитаю, чтобы он получалright сообщение. Но если ваш проект отличается от других, вы легко можете получить другое "право" ответ!

Ваш ответ на вопрос