Как написать unit test для "T должен быть ссылочным типом"?
Рассмотрим:
class MyClass<T> where T : class
{
}
В этом случае предложение where использует спецификацию, что MyClass является только общим ссылочным типом.
В идеале я должен иметь unit test, который проверяет эту спецификацию. Однако этот unit test, очевидно, не будет работать, но он объясняет, что я пытаюсь выполнить:
[Test]
[DoesNotCompile()]
public void T_must_be_a_reference_type()
{
var test = new MyClass<int>();
}
Что я могу сделать, чтобы проверить спецификацию, которая реализована, не позволяя компилировать код?
ИЗМЕНИТЬ
Дополнительная информация: Хорошо, поэтому мои аргументы в пользу этого (ха-ха) заключаются в том, что я слежу за методологией TDD, в которой вы не можете писать код, если у вас нет неудачного unit test. Скажем, у вас было это:
class MyClass<T> { }
Какой тест вы можете написать, если бы T не был классом? Что-то вроде default(T) == null
?
Далее EDIT:
Итак, после "анализа основных причин" проблема заключается в том, что я полагался на default(T)
null
у потребителя этого класса неявным образом. Я смог реорганизовать этот потребительский код в другой класс и указать там ограничение общего типа (ограничение на class
), что фактически делает этот код не компилируемым, если кто-то должен удалить ограничение на класс, о котором я говорю выше.
Ответы
Ответ 1
Зачем вам нужен unit test для этого? Вы пишете unit test для метода, такого как
public void Foo(string x)
проверить, что он может принимать только строки, а не целые числа? Если нет, что вы видите как разницу?
EDIT: просто немного менее причудливый: в этом случае спецификация подтверждается объявлением. Тесты обычно должны проверять поведение. Это одна из вещей, которые мне нравятся в кодовых контрактах: я не чувствую необходимости в unit test контрактах, если они не выражают что-то сложное - в этом случае это сложность, которую я тестирую, а не "контракты принудительно", бит.
EDIT: для ответа на вопрос:
Какой тест вы можете написать, который потерпит неудачу, если T не будет классом?
Вы можете написать что-то вроде:
Type definition = typeof(MyClass<>);
Assert.Throws<ArgumentException>(() => definition.MakeGenericType(typeof(int)));
Однако, похоже, это противоречит реальной цели тестирования...
Ответ 2
Вам не следует проверять, выполняет ли компилятор свою работу. Если вы укажете это в коде, этого достаточно. С точки зрения кода это примерно такое же:
[Test]
public void Test_whether_add_works()
{
int i = 1 + 2;
Assert.AreEqual(3, i);
}
Ответ 3
Это отличный вопрос! Так много согласны с вашим подходом, основанным на проверке. То, с чем вы боретесь, на самом деле является столкновением двух парадигм. Старая парадигма о том, что программы должны быть проверены правильно, используя математику, не запуская их (наследие наших родословных профессий в математике) и новую парадигму, которую programd следует доказать правильно, выполнив пример использования, т.е. Тесты. Итак, что вы собираетесь попробовать, это применить практику новой парадигмы в артефакте старой парадигмы, которая, конечно же, действительно работает...
Подробнее о дихотомии типов и тестов см. в этой замечательной статье Криса Смита, http://web.archive.org/web/20080822101209/http://www.pphsg.org/cdsmith/types.html
Ответ 4
Вы пишете правильный unit test? Похоже, что вы собираетесь тестировать компилятор С#, но не ваш код.