Рассмотрим реализацию шаблона репозитория (или аналогичного). Я постараюсь сделать пример / иллюстрацию максимально краткими:
interface IRepository<T>
{
void Add(T entity);
}
public class Repository<T> : IRepository<T>
{
public void Add(T entity)
{
// Some logic to add the entity to the repository here.
}
}
В этой конкретной реализации, репозиторий определяется интерфейсом IRepository, чтобы иметь один метод, который добавляет объект в репозиторий, тем самым делая Repository зависимым от универсального типа T (также, репозиторий должен неявно зависеть от другого типа TDataAccessLayer , поскольку абстракция - это вся точка шаблона репозитория (однако эта зависимость в настоящее время недоступна). На данный момент, насколько я понимаю, у меня есть два варианта: модульное тестирование и интеграционное тестирование.
В тех случаях, когда можно предположить, что интеграционное тестирование имеет большее количество движущихся частей, я бы предпочел сначала модульное тестирование, чтобы как минимум проверить базовую функциональность. Однако без создания какого-либо свойства «сущности» (универсального типа T) я не вижу способа утверждать, что какая-либо логика фактически выполняется в методе Add () реализации Repository.
Может быть, есть что-то среднее между модульным тестированием и интеграционным тестированием, которое позволяет (с помощью Reflection или другими способами) проверить, что конкретные точки выполнения были достигнуты в тестируемом модуле?
Единственное объяснение, которое я придумал для этой конкретной проблемы, - это дальнейшее абстрагирование уровня доступа к данным из хранилища, в результате чего метод Add () принимает не только аргумент сущности, но и аргумент доступа к данным. Однако мне кажется, что это может нанести ущерб цели шаблона репозитория, поскольку теперь пользователь репозитория должен знать о уровне доступа к данным.
В отношении запроса примеров:
(1) Что касается модульного тестирования, я не уверен, что что-то вроде репозитория могло бы быть модульным тестированием с моим пониманием современных методов тестирования. Поскольку репозиторий является абстракцией (оболочкой) вокруг определенного уровня доступа к данным, кажется, что единственным методом проверки был бы интеграционный тест? (Конечно, интерфейс репозитория не может быть привязан к какому-либо конкретному DAL, но любой реализованный репозиторий должен быть обязательно привязан к конкретной реализации DAL, поэтому необходимо иметь возможность проверить, что метод Add () действительно выполняет некоторую работу).
(2) Что касается интеграционного тестирования, то тест, как я понимаю, будет проверять метод Add (), выполняющий работу, фактически вызывая метод Add () (который должен добавить запись в хранилище), и затем проверьте, что данные действительно были добавлены в хранилище (или, возможно, базу данных в определенном сценарии). Это может выглядеть примерно так:
[TestMethod]
public void Add()
{
Repository<Int32> repository = new Repository<Int32>();
Int32 testData = 10;
repository.Add(testData);
// Intended to illustrate the point succinctly. Perhaps the repository Get() method would not
// be called (and a DBCommand unrelated to the repository issued instead). However, assuming the
// Get() method to have been previously verified, this could work.
Assert.IsTrue(testData == repository.Get(testData));
}
Таким образом, в этом случае, предполагая, что хранилище является оберткой вокруг некоторого логического уровня базы данных, база данных фактически подвергается двойному удару во время теста (один раз во время вставки и один раз во время получения).
Теперь то, что я мог бы счесть полезным, было бы техникой проверки того, что определенный путь выполнения выбран во время выполнения. Примером может быть то, что, если передается ненулевая ссылка, убедитесь, что выбран путь выполнения A, а если передана нулевая ссылка, проверьте путь выполнения B. Кроме того, возможно, можно было бы убедиться, что конкретный запрос LINQ должен был быть выполнен. Таким образом, база данных никогда не подвергается действию во время теста (что позволяет создавать прототипы и разрабатывать реализацию без реального DAL).