Как написать модульный тест для "T должен быть ссылочным типом"? - PullRequest
11 голосов
/ 27 октября 2010

Рассмотрим:

class MyClass<T> where T : class
{
}

В этом случае условие where обеспечивает применение спецификации, согласно которой MyClass является только универсальным типом ссылочного типа.

В идеале мне нужно выполнить модульный тест, которыйпроверяет эту спецификацию.Тем не менее, этот модульный тест, очевидно, не будет работать, но он объясняет, что я пытаюсь выполнить:

[Test]
[DoesNotCompile()]
public void T_must_be_a_reference_type()
{
    var test = new MyClass<int>();
}

Что я могу сделать, чтобы протестировать спецификацию, которая реализована, не позволяя скомпилировать код?

РЕДАКТИРОВАТЬ :

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

class MyClass<T> { }

Какой тест вы можете написать, который провалился бы, если бы T не был классом?Что-то вроде default(T) == null?

Дальнейшее редактирование :

Так что после «анализа первопричины» проблема заключается в том, что я полагался на то, что default(T)null у потребителя этого класса, неявным образом.Я смог преобразовать этот потребительский код в другой класс и указать там ограничение универсального типа (ограничив его class), что фактически делает этот код не компилируемым, если кто-то снимает ограничение на класс, о котором я говорю выше.

Ответы [ 4 ]

25 голосов
/ 27 октября 2010

Зачем вам для этого юнит-тест? Вы пишете модульный тест для метода, такого как

public void Foo(string x)

чтобы проверить, что он может принимать только строки, а не целые числа? Если нет, то в чем вы видите разницу?

РЕДАКТИРОВАТЬ: Просто чтобы быть немного менее прихотливым: в этом случае спецификация подтверждается декларацией . Тесты должны обычно проверять поведение . Это одна из вещей, которые мне нравятся в Code Contracts: я не чувствую необходимости модульного тестирования контрактов, если они не выражают что-то сложное - в этом случае я буду тестировать эту сложность, а не бит «контракты принудительно применяются» .

РЕДАКТИРОВАТЬ: Чтобы ответить на вопрос, отредактируйте:

Какой тест вы можете написать, который провалился бы, если бы T не был классом?

Вы могли бы написать что-то вроде:

Type definition = typeof(MyClass<>);
Assert.Throws<ArgumentException>(() => definition.MakeGenericType(typeof(int)));

Однако, похоже, что это идет вразрез с реальной целью тестирования ...

9 голосов
/ 27 октября 2010

Вы не должны проверять, выполняет ли компилятор свою работу.Если вы укажете это в коде, этого достаточно.С точки зрения кода это примерно так:

[Test]
public void Test_whether_add_works()
{
    int i = 1 + 2;

    Assert.AreEqual(3, i);
}
3 голосов
/ 27 октября 2010

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

Подробнее о дихотомии типов и тестов читайте в этой превосходной статье Криса Смита, http://web.archive.org/web/20080822101209/http://www.pphsg.org/cdsmith/types.html

2 голосов
/ 27 октября 2010

Вы пишете правильный юнит-тест? Похоже, вы собираетесь тестировать компилятор C #, но не ваш код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...