Система TDD В стадии тестирования Шаблонов создания (автофиксация)

StackOverflow https://stackoverflow.com/questions/3158148

  •  01-10-2019
  •  | 
  •  

Вопрос

Я пытаюсь использовать Фабрика SUT "шаблон" для создания моего SUT.

Учитывая структуру SUT:

namespace MySut
{
    public class Dep1
    {
    }

    public class Dep2
    {
    }

    public class Sut
    {
        public Sut( Dep1 dep1, Dep2 dep2 )
        {
        }
    }
}

Я использую Автоматическая фиксация, и мне интересно, какой наилучший способ свернуть следующие спецификации и связанный с ними метод SUT factory [ценный, но] трудоемкий:

namespace MySpecifications
{
    using MySut;
    public class MySpecification
    {
        public void TestCore()
        {
            // Dont care about dependencies, testing core functionality
            var sut = CreateSut();
        }

        public void TestDep1Interaction()
        {
            // Dont care about Dep2, want to observe stuff on the Dep1 dependent object
            var sut = CreateSut( new Mock<Dep1>().Object );
        }

        public void TestDep2Interaction()
        {
            // Dont care about Dep1, want to observe stuff on the Dep2 dependent object
            var sut = CreateSut( new Mock<Dep2>().Object );
        }

        private object CreateSut( )
        {
            return CreateSut( CreateDep1(), CreateDep2() );
        }

        private object CreateSut( Dep1 dep1 )
        {
            return CreateSut( dep1, CreateDep2() );
        }

        private object CreateSut( Dep2 dep2 )
        {
            return CreateSut( CreateDep1(), dep2 );
        }

        private Sut CreateSut( Dep1 dep1, Dep2 dep2 )
        {
            return new Sut( dep1, dep2 );
        }

        private static Dep1 CreateDep1()
        {
            return new Fixture().CreateAnonymous<Dep1>();
        }

        private static Dep2 CreateDep2()
        {
            return new Fixture().CreateAnonymous<Dep2>();
        }
    }
}

к чему - то вроде:

    public class MyAutoFixturedSpecification
    {
        public void TestCore()
        {
            // Dont care about dependencies, testing core functionality
            var sut = CreateSut();
        }

        public void TestDep1Interaction()
        {
            // Dont care about Dep2, want to observe stuff on the Dep1 dependent object
            var sut = CreateSut( new Mock<Dep1>().Object );
        }

        public void TestDep2Interaction()
        {
            // Dont care about Dep1, want to observe stuff on the Dep2 dependent object
            var sut = CreateSut( new Mock<Dep2>().Object );
        }

        private object CreateSut( params object[] injectedNonAnonymouses )
        {
            return new Fixture(  ).Build<Sut>(  )./*??????*/;
        }
    }

или:

    public class MyAnticipatedAutoFixturedSpecification
    {
        public void TestCore()
        {
            // Dont care about dependencies, testing core functionality
            var sut = new Fixture(  ).Build<Sut>().CreateAnonymous(  );
        }

        public void TestDep1Interaction()
        {
            // Dont care about Dep2, want to observe stuff on the Dep1 dependent object
            var sut = new Fixture().Build<Sut>()/*.With( new Mock<Dep1>().Object )*/.CreateAnonymous();
        }

        public void TestDep2Interaction()
        {
            // Dont care about Dep1, want to observe stuff on the Dep2 dependent object
            var sut = new Fixture().Build<Sut>()/*.With( new Mock<Dep2>().Object )*/.CreateAnonymous();
        }
    }

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

namespace MySutWithNewDependency
{
    public class Dep1
    {
    }

    public class Dep2
    {
    }

    public class Dep3
    {
    }

    public class Sut
    {
        public Sut( Dep1 dep1, Dep2 dep2, Dep3 dep3 )
        {
        }
    }
}

Хотя понятие контейнера автоматической настройки пересекается, я все еще не ищу золотой молоток - просто способ иметь возможность моделировать 0 или 1 объект одновременно и в то же время иметь возможность настраивать создание зависимых объектов без необходимости повторять явные вызовы конструктора Sut всякий раз, когда изменяется его набор зависимостей.

(Также использую xUnit.net (стиль SubSpec), Moq, Ninject2 (хотя не хочу использовать DI в моих спецификациях))

Это было полезно?

Решение

AutoFixture может более или менее сделать все это за вас без всех этих дополнительных строительных лесов.Я бы начал с базового приспособления и использовал его для решения Sut:

var fixture = new Fixture();
var sut = fixture.CreateAnonymous<Sut>();

Это предполагает, что Dep1 и Dep2 могут быть созданы автоматически с помощью AutoFixture, но, как представлено, они могут, потому что у них есть конструкторы по умолчанию.

Когда вы хотите переопределить определенный тип, вы можете использовать метод Register следующим образом:

var fixture = new Fixture();

var mock = new Mock<Dep1>();
fixture.Register(mock.Object);
// Setup mock if necessary...

var sut = fixture.CreateAnonymous<Sut>();

Это приведет к fixture для использования mock.Object в любое время Dep1 необходим, в том числе и тогда, когда Sut вызывается конструктор.Это определенно соответствует вашему требованию надежности перед лицом развивающихся конструкторов, и это одна из главных причин, по которой AutoFixture был построен именно так.

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

Я лично использую AutoFixture в качестве контейнера для автоматической настройки. Это обсуждение содержит подсказку о том, как это было бы возможно с API AutoFixture 1.1, но новое ядро для AutoFixture 2.0 предоставит гораздо лучшие возможности расширения.Когда я доберусь до этого, я напишу сообщение в блоге на эту тему.

P.S.Извините за поздний ответ, но до сих пор я не видел вашего вопроса.В будущем, не стесняйтесь отправлять мне сообщения (например,в Twitter) для более быстрого ответа.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top