Domanda

Sto cercando di utilizzare SUT fabbrica 'modello' per creare la mia SUT.

Data la struttura SUT:

namespace MySut
{
    public class Dep1
    {
    }

    public class Dep2
    {
    }

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

AutoFixture , e mi chiedo qual è il modo migliore per comprimere le seguenti specifiche e SUT associato metodo factory [prezioso, ma] busywork:

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>();
        }
    }
}

a qualcosa di simile:

    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>(  )./*??????*/;
        }
    }

o

    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();
        }
    }
.

cioè, eliminando tutte le cianfrusaglie fabbrica, in modo che le mie specifiche possono facilmente far fronte con una transizione a:

namespace MySutWithNewDependency
{
    public class Dep1
    {
    }

    public class Dep2
    {
    }

    public class Dep3
    {
    }

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

Mentre non v'è sovrapposizione con il concetto di un contenitore automocking, sto ancora non in cerca di un martello d'oro - solo un modo per essere in grado di prendere in giro 0 o 1 cosa alla volta e tuttavia in grado di personalizzare la creazione di dipendenti oggetti senza dover rivisitare chiamate esplicite al costruttore Sut ogni volta che la sua insieme di dipendenze modifiche.

(anche utilizzando xUnit.net (stile SubSpec), Moq, Ninject2 (anche se non volete utilizzare DI nelle mie specifiche))

È stato utile?

Soluzione

AutoFixture può più o meno fare tutto questo per voi, senza tutto ciò che impalcature in più. Mi piacerebbe iniziare con un fissaggio di base e lo uso per risolvere Sut:

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

Questo presuppone che Dep1 e Dep2 possono essere creati automaticamente da AutoFixture, ma come presentato, possono perché hanno costruttori di default.

Quando si desidera sovrascrivere un tipo specifico, è possibile utilizzare il metodo Register in questo modo:

var fixture = new Fixture();

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

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

Questo farà sì che fixture ad uso mock.Object è necessaria alcuna Dep1 momento, anche quando il costruttore Sut viene richiamato. Questo si inserisce sicuramente la vostra esigenza di essere robusti a fronte di costruttori in evoluzione, e uno dei motivi principali AutoFixture è stato costruito in quel modo.

In uno scenario più realistico, Dep1 e Dep2 potrebbero essere le interfacce, nel qual caso si potrebbe desiderare di registrarli come parte di un 'default Fixture'. Questo è certamente anche forse perché che ultima chiamata al registro vince . Ciò significa che è possibile configurare un esempio Apparecchio con buone impostazioni di default e di essere ancora in grado di sostituire i tipi specifici ogni volta che avete bisogno di fare questo.

Io personalmente uso AutoFixture come un contenitore auto-beffardo. Questa discussione fornisce un accenno a come questo sarebbe possibile con l'AutoFixture 1.1 API, ma il nuovo kernel per AutoFixture 2.0 forniranno opzioni migliori di estensibilità. Quando arrivo ad esso, scriverò un post su questo argomento.

P.S. Mi dispiace per il ritardo di risposta, ma non ho visto la tua domanda prima d'ora. In futuro, si sentono liberi di ping me (per esempio su Twitter) per una più rapida risposta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top