TDD, Mocking, внедрение зависимостей и принцип DRY - PullRequest
2 голосов
/ 28 октября 2009

У меня есть класс контроллера, который принимает несколько параметров в ctor, который вводится во время выполнения.

Пример:

    public ProductController(IProductRepositort productRepository, 
IShippingService shippingService, IEmailProvider emailProvider)
    {
    ...
    }

Я обнаружил, что методы испытаний становятся огромными. Я настраиваю методы следующим образом:

[Test]
public void CanSendProduct()
{
    //Code to set up stub
                List<Product> products = new List<Product>();
                for (int i = 0; i < length; i++)
                {
                    products.Add(new Product()));
                }

                var mockProductRepository = new Mock<IProductRepository>();
                mockProductRepository.Setup(x => x.GetProducts()).Returns(products);

                //Code to set up stub
                ....
                ....   
                var mockShippingService = new Mock<IShippingService>();
                mockShippingService.Setup(x => x.GetShippers()).Returns(shippers);

                //Code to set up stub
                .....
                .....
                 var mockEmailProvider = new Mock<IEmailProvider>();
                mockEmailProvider.Setup(x => x.Send()).Returns(provider);

                //Execute Test
                ....
                ....

                //Assert
                ....
                ....
}

Очевидно, что нецелесообразно повторять настройку макета в каждом методе этого тестового класса.

Как я могу создавать богатые объекты-насмешки, которые позволяют мне Поведенческая проверка моих тестов и в то же время минимизировать боль при настройке?

Каковы рекомендации TDD для решения этой проблемы?

Спасибо

Ответы [ 3 ]

6 голосов
/ 28 октября 2009

Если ваша тестовая среда поддерживает функции установки / разрыва, которые будут вызываться до и после каждого теста, создайте и уничтожьте некоторые фиктивные объекты «по умолчанию» в этих функциях. Ваши тесты могут просто использовать их, а для особых случаев, когда фиктивные объекты по умолчанию у вас не работают, вы можете просто игнорировать их и создавать локальные фиктивные объекты в этих тестах.

0 голосов
/ 28 октября 2009

Я бы просто извлек этот код в методы (если ваша фиктивная среда требует, чтобы вы передавали фабрику имитатора, измените сигнатуру при необходимости):

private Mock<IProductRepository> SetupStandardMockProductRepository() {
    List<Product> products = new List<Product>();
    for (int i = 0; i < length; i++) {
        products.Add(new Product()));
    }    
    var mockProductRepository = new Mock<IProductRepository>();
    mockProductRepository.Setup(x => x.GetProducts()).Returns(products);
}

// ... and so forth

Тогда в ваших тестах:

var mockProductRepository = SetupStandardMockProductRepository();

// or make these static properties of some central test class, like this:
var mockProductRepository = Stubs.StandardProductRepository;
0 голосов
/ 28 октября 2009

Используйте поведенческое или функциональное тестирование. Похоже, ваш в C # или Java? В любом случае я бы порекомендовал FItnesse , но есть и другие. Что касается юнит-тестов, я бы, вероятно, использовал контейнер IOC, такой как Winsor / Castle или Spring, тогда вы можете настроить контейнер для тестов, заполненных Mocks, а не "настоящими" объектами.

...