Как написать модульный тест для небезопасной коллекции потока - PullRequest
3 голосов
/ 23 января 2011

Я пишу двусвязный список, используя подход TDD. Этот тип коллекции не является потокобезопасным. Для реализации интерфейса ICollection мой класс списка должен иметь несколько открытых свойств (включая IsSynchronized и SyncRoot, которые используются для обеспечения поточно-ориентированного способа использования коллекции). Код этих двух свойств довольно прост:

public bool IsSynchronized { get { return false; } }

private readonly object _syncRoot = new object();
public object SyncRoot { get { return _syncRoot; } }

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

Ответы [ 2 ]

5 голосов
/ 23 января 2011

мой класс списка должен иметь несколько открытых свойств (включая IsSynchronized и SyncRoot

Это не так. Это восходит к .NET версии 1 и широко считается гигантской ошибкой. Это создало ложное чувство безопасности потоков, которое доставило многим программистам серьезные проблемы. Такой класс не был на самом деле потокобезопасным во всех случаях, итерации для одного не были. Он был полностью исключен из классов общей коллекции .NET 2.0. И вы не должны реализовывать ICollection, современный класс коллекции должен быть универсальным и реализовывать ICollection<T>. К сожалению, это все еще требует реализации IEnumerable, наследие, от которого мы, вероятно, никогда не избавимся. Вы реализуете это с явной реализацией, такие методы не являются публичными.

Второстепенное соображение заключается в том, является ли реализация ICollection <> хорошей идеей. Связанный список делает члена, такого как Count, дорогим, это по природе O (n). Вам нужно отслеживать количество элементов в списке отдельно, чтобы оно составляло O (1). Класс .NET LinkedList <>, также класс коллекции двусвязных списков, делает это.

0 голосов
/ 23 января 2011

Я бы сказал, что это относится к категории , а не к вашей ответственности . Свойство SyncRoot присутствует в случае, если кто-то, использующий ваш класс коллекции, хочет синхронизировать чтение / запись, предоставляя удобный объект для блокировки - и ничего более. (На самом деле цель этого свойства была широко понята неправильно; само свойство часто рассматривается как довольно бесполезное, как указывал Ганс .)

Если вы чувствуете, что у вас есть достаточные причины для реализации этого интерфейса, все равно это тот случай, когда синхронизация полностью выходит за рамки самого вашего типа (как вы указали, имея свойство IsSynchronized return false); как таковой, он действительно не должен быть проверен модулем на вашем конце.

На самом деле, я полагаю, что разработчики интерфейса ICollection довольно часто просто игнорируют свойство SyncRoot (установите его на null). Это должно вам кое-что сказать.

Для модульного теста вы можете просто проверить, что свойство SyncRoot не null.

...