Как написать 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? Похоже, что вы собираетесь тестировать компилятор С#, но не ваш код.