Что целью поблочного тестирования является интерфейсный репозиторий

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

  • Как модульный тест, что значение - я получающий путем тестирования ICustomerRepository этим способом?
  • При каких условиях был бы ниже тестового сбоя?
  • Для тестов этой природы желательно делать тесты, которые я знаю, должен перестать работать? т.е. ищите идентификатор 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();
}
6
задан ahsteele 17 June 2010 в 23:09
поделиться

4 ответа

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

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

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

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

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

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

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

5
ответ дан 8 December 2019 в 13:44
поделиться

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

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

2
ответ дан 8 December 2019 в 13:44
поделиться

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

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

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

6
ответ дан 8 December 2019 в 13:44
поделиться

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

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

4
ответ дан 8 December 2019 в 13:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: