ASP.NET MVC - Как провести модульное тестирование границ в шаблоне репозитория? - PullRequest
5 голосов
/ 13 мая 2010

Учитывая базовый интерфейс хранилища:

public interface IPersonRepository
{
    void AddPerson(Person person);
    List<Person> GetAllPeople();
}

С базовой реализацией:

public class PersonRepository: IPersonRepository
{
    public void AddPerson(Person person) 
    {
        ObjectContext.AddObject(person);
    }

    public List<Person> GetAllPeople()
    {
        return ObjectSet.AsQueryable().ToList();
    }
}

Как вы можете проверить это осмысленно? Поскольку он пересекает границу и физически обновляет и считывает из базы данных, это не модульный тест, а интеграционный тест.

Или это неправильно - сначала пытаться выполнить юнит-тестирование? Разве у меня должны быть только интеграционные тесты в репозитории?

Я гуглю тему, и блоги часто говорят о создании заглушки, которая реализует IRepository:

public class PersonRepositoryTestStub: IPersonRepository
{
    private List<Person> people = new List<Person>();
    public void AddPerson(Person person) 
    {
        people.Add(person);
    }

    public List<Person> GetAllPeople()
    {
        return people;
    }
}

Но это не модульное тестирование PersonRepository, оно тестирует реализацию PersonRepositoryTestStub (не очень полезно).

Ответы [ 4 ]

7 голосов
/ 13 мая 2010

В этом конкретном случае я думаю, что вам не нужно делать модульный тест для вашего класса репозитория, поскольку реализация просто вызывает объект ObjectContext, так что это будет похоже на тестирование того, что вы не создали (что это не идея). Если у вас нет сложной логики, я не рекомендую тратить время на создание модульного теста для этого класса. То, что вы говорите о PersonRepositoryTestStub, является фальшивой реализацией репозитория для тестирования уровня выше вашего DAL.

2 голосов
/ 14 мая 2010

Я столкнулся с той же проблемой. Я написал множество модульных тестов для реализации моего интерфейса репозитория, который был поддельным репозиторием. Вскоре после его завершения я понял, что написал модульный тест для проверки поддельного хранилища и написал поддельный репозиторий просто для поддержки модульных тестов. Это казалось большим количеством бесполезного кода.

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

Итак, я решил оставить там модульные тесты для поддельного репозитория, поскольку они полезны для тестирования моего поддельного репозитория, чтобы я мог быть уверен, что на более высоких уровнях моего приложения используются полностью протестированные подделки.

Другими словами, поддельное хранилище и модульные тесты против поддельного хранилища являются «опорой» для более высоких уровней приложений и модульных тестов против более высоких уровней приложения.

Надеюсь, это поможет.

1 голос
/ 13 мая 2010

Время, когда я думаю, что этот тип тестирования имеет смысл, это когда ваш интерфейс репозитория является универсальным. Э.Г.

public interface IEntity
{
    int Id { get; set; }
}

public interface IRepository<TEntity>
    where TEntity : IEntity
{
    void Add(TEntity entity);
    List<TEntity> GetAll();
}

Если у вас есть несколько реализаций этого интерфейса, то также возможно написать универсальное тестовое устройство, которое тестирует этот интерфейс, позволяя вам протестировать несколько реализаций репозитория с помощью одного тестового устройства. Этот подход не делает различий между модульными и интеграционными тестами, потому что он не знает, что такое реализация.

Дайте мне знать, если вас это интересует, и я могу опубликовать полный пример.

0 голосов
/ 13 мая 2010

Я бы протестировал уровень бизнес-логики, который напрямую зависит от реализации DAL (имеет сильную ссылку на точную реализацию DAL) или косвенно (абстрагируется от DAL через интерфейсы).

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

...