Какова цель модульного тестирования репозитория интерфейса - PullRequest
6 голосов
/ 18 июня 2010

Я тестирую интерфейс ICustomerRepository, используемый для получения объектов типа Customer.

  • Как юнит-тест, какое значение я получаю, тестируя ICustomerRepository таким образом?
  • При каких условиях приведенный ниже тест не пройден?
  • Для тестов такого рода целесообразно ли проводить тесты, которые, как я знаю, должны провалиться? то есть ищите id 4, когда я знаю, что только поместил 5 в хранилище

Возможно, я упускаю что-то очевидное, но, похоже, интеграционные тесты класса, реализующего ICustomerRepository, будут более ценными.

[TestClass]
public class CustomerTests : TestClassBase
{
    private Customer SetUpCustomerForRepository()
    {
        return new Customer()
        {
            CustId = 5,
            DifId = "55",
            CustLookupName = "The Dude",
            LoginList = new[]
            {
                new Login { LoginCustId = 5, LoginName = "tdude" },
                new Login { LoginCustId = 5, LoginName = "tdude2" }
            }
        };
    }

    [TestMethod]
    public void CanGetCustomerById()
    {
        // arrange
        var customer = SetUpCustomerForRepository();
        var repository = Stub<ICustomerRepository>();

        // act
        repository.Stub(rep => rep.GetById(5)).Return(customer);

        // assert
        Assert.AreEqual(customer, repository.GetById(5));
    }
}

Базовый класс испытаний

public class TestClassBase
{
    protected T Stub<T>() where T : class
    {
        return MockRepository.GenerateStub<T>();
    }
}

ICustomerRepository и IRepository

public interface ICustomerRepository : IRepository<Customer>
{
    IList<Customer> FindCustomers(string q);
    Customer GetCustomerByDifID(string difId);
    Customer GetCustomerByLogin(string loginName);
}

public interface IRepository<T>
{
    void Save(T entity);
    void Save(List<T> entity);
    bool Save(T entity, out string message);
    void Delete(T entity);
    T GetById(int id);
    ICollection<T> FindAll();
}

Ответы [ 4 ]

6 голосов
/ 18 июня 2010

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

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

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

5 голосов
/ 18 июня 2010

Правило № 1 тестирования:

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

Как правильно сказали другие авторы, вы заглушаете интерфейс, а затем вызываете заглушку - это ничего не доказывает,ваш рабочий код работает.

Что такое заглушка?

Заглушки используются для предоставления постоянных значений для управления некоторыми аспектами тестируемого класса.Например, скажем, у вас есть CustomerService, который имеет экземпляр типа ICustomerRepository.Если вы хотите увидеть, что CustomerService может корректно обработать ошибку, когда хранилище пусто, вы должны заглушить метод ICustomerRepository GetCustomerById, чтобы ничего не возвращать / null / выдать исключение, а затем убедиться, что CustomerService метод сделал правильную вещь (например, вернуть клиенту не найденный результат).

Т.е. заглушка - просто соавтор, который помогает вам достичь определенного состояния / поведения, представляющего интерес.Мы тестируем CustomerService, а отметка ICustomerRepository просто помогает нам достичь нашей цели.

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

4 голосов
/ 18 июня 2010

Интерфейсы, по определению, просто контракты, поэтому нет кода для тестирования.Вы хотите написать модульные тесты с конкретной реализацией (ями) интерфейса, потому что именно там живет реальный исполняемый код.

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

2 голосов
/ 18 июня 2010

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

Следуйте ответу dcp.Интерфейс - это объявление методов.Вы должны проверить их реализацию.

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