Question

Je suis en train d'utiliser SUT Factory 'le modèle' pour créer mon SUT.

Compte tenu de la structure SUT:

namespace MySut
{
    public class Dep1
    {
    }

    public class Dep2
    {
    }

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

J'utilise AutoFixture , et je me demande quelle est la meilleure façon de s'effondrer les spécifications suivantes et SUT associés méthode d'usine [valeur mais] 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>();
        }
    }
}

à quelque chose comme:

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

ou

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

i.e., enlever tous les déchets de l'usine, de sorte que mes spécifications peuvent facilement faire face à une transition vers:

namespace MySutWithNewDependency
{
    public class Dep1
    {
    }

    public class Dep2
    {
    }

    public class Dep3
    {
    }

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

Bien qu'il y ait un chevauchement avec la notion d'un conteneur de automocking, je suis toujours pas à la recherche d'un marteau d'or - juste une façon de pouvoir se moquer de 0 ou 1 chose à la fois et pourtant être en mesure de personnaliser la création de personnes à charge des objets sans avoir à revenir sur les appels explicites au constructeur Sut chaque fois que son ensemble de changements de dépendances.

(également en utilisant xUnit.net (style subSpec), Moq, Ninject2 (bien que ne veulent pas utiliser DI dans mon cahier des charges))

Était-ce utile?

La solution

AutoFixture peut plus ou moins faire tout cela pour vous, sans tout cet échafaudage supplémentaire. Je commence avec un appareil de base et l'utiliser pour résoudre Sut:

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

Cela suppose que Dep1 et Dep2 peut être créé automatiquement par AutoFixture, mais tel que présenté, ils peuvent, car ils ont des constructeurs par défaut.

Lorsque vous voulez remplacer un type spécifique, vous pouvez utiliser la méthode enregistrer comme ceci:

var fixture = new Fixture();

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

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

Cela entraînera fixture à l'utilisation mock.Object tout Dep1 de temps est nécessaire, y compris lorsque le constructeur de Sut est invoquée. Cela correspond certainement à votre exigence d'être robuste face à des constructeurs en évolution, et l'une des principales raisons AutoFixture a été construit comme ça.

Dans un scénario plus réaliste, dep1 et dep2 pourraient être des interfaces, dans ce cas, vous voudrez peut-être de les inscrire dans le cadre d'un « défaut Fixture ». Ceci est certainement aussi peut-être parce que dernier appel au registre gagne . Cela signifie que vous pouvez configurer une instance Fixture avec quelques bons paramètres par défaut et toujours être en mesure de passer outre des types spécifiques chaque fois que vous devez faire.

J'utilise personnellement AutoFixture comme conteneur auto-moqueur. Cette discussion donne une indication sur la façon dont cela serait possible avec le AutoFixture 1.1 API, mais le nouveau noyau pour AutoFixture 2.0 fournira beaucoup de meilleures options d'extensibilité. Quand j'arrive, je vais écrire un billet de blog sur ce sujet.

P.S. Désolé pour la réponse tardive, mais je ne vois pas votre question avant maintenant. À l'avenir, ne hésitez pas à me ping (par exemple sur Twitter) pour une réponse plus rapide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top