Система. Диагностика. Контракты. ContractException не доступен в моем тестовом проекте. Обратите внимание, что этот код просто самостоятельно бездельничает с моей солнечной новой копией Visual Studio, но я хотел бы знать то, что я делаю неправильно.
Я использую профессиональный выпуск VS, поэтому у меня нет статической проверки. Для тихого использования контрактов кода (который я люблю), я изобразил единственный способ, которым может работать мой метод, должен поймать исключение, которое выдается во времени выполнения, но я не нахожу это возможным.
TestMethod
[TestMethod, ExpectedException(typeof(System.Diagnostics.Contracts.ContractException))]
public void returning_a_value_less_than_one_throws_exception()
{
var person = new Person();
person.Number();
}
Метод
public int Number()
{
Contract.Ensures(Contract.Result<int>() >= 0);
return -1;
}
Ошибка
Error 1 'System.Diagnostics.Contracts.ContractException' is inaccessible due to its protection level.
Править
После того, как еще некоторые думали, что я пришел к выводу обсужденный в комментариях, а также следующем. Учитывая метод, если это имело требование, которое могло бы быть выражено в форме Контракта Кода, я запишу тесты как таковые.
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void value_input_must_be_greater_than_zero()
{
// Arrange
var person = new Person();
// Act
person.Number(-1);
}
Это гарантировало бы, что контракт является частью кода и не будет удален. Это потребовало бы, чтобы Контракт Кода на самом деле выдал указанное исключение как бы то ни было. В некоторых случаях это не требовалось бы как бы то ни было.
Это преднамеренно, хотя и небольшая боль для тестирования.
Дело в том, что в производственном коде вы никогда не должны хотеть ловить исключение контракта; это указывает на ошибку в вашем коде, поэтому вы не должны ожидать этого больше, чем произвольные неожиданные исключения, которые вы можете захотеть поймать прямо в верхней части стека вызовов, чтобы вы могли перейти к следующему запросу. В принципе, вы не должны рассматривать исключения из контракта как те, которые могут быть «обработаны» как таковые.
Теперь, для тестирования это боль... но вы действительно хотите проверить свои контракты в любом случае? Разве это не похоже на тестирование того, что компилятор останавливает вас от передачи строки string
методу, который имеет параметр int
? Вы объявили контракт, он может быть задокументироват соответствующим образом и применен соответствующим образом (во всяком случае, на основе настроек).
Если вы do хотите протестировать исключения из контракта, вы можете либо поймать голое Exception
в тесте и проверить его полное имя, либо вы можете повозиться с событием Contract.ContractFailed
.. Я ожидаю, что фреймворки модульного тестирования будут иметь встроенную поддержку для этого с течением времени, но это займет некоторое время, чтобы добраться туда. В то же время вы, вероятно, хотите иметь служебный метод, чтобы ожидать нарушения контракта. Одна из возможных реализаций:
const string ContractExceptionName =
"System.Diagnostics.Contracts.__ContractsRuntime.ContractException";
public static void ExpectContractFailure(Action action)
{
try
{
action();
Assert.Fail("Expected contract failure");
}
catch (Exception e)
{
if (e.GetType().FullName != ContractExceptionName)
{
throw;
}
// Correct exception was thrown. Fine.
}
}
в vs2010 rtm полное название было изменено на "System.Diagnostics.Contracts.__ContractsRuntime+ContractException". HTH