Question

Classes scellées moqueuses peut être assez pénible.Je privilégie actuellement un Modèle d'adaptateur pour gérer ça, mais quelque chose qui continue de me paraître bizarre.

Alors, quelle est la meilleure façon de vous moquer des cours scellés ?

Les réponses Java sont plus que bienvenues.En fait, j'imagine que la communauté Java s'occupe de ce problème depuis plus longtemps et a beaucoup à offrir.

Mais voici quelques opinions sur .NET :

Était-ce utile?

La solution

Ma règle générale est que les objets dont je dois me moquer doivent également avoir une interface commune.Je pense que c'est correct du point de vue de la conception et rend les tests beaucoup plus faciles (et c'est généralement ce que vous obtenez si vous faites du TDD).Pour en savoir plus, consultez le blog Google Testing. dernier message (Voir point 9).

De plus, je travaille principalement en Java depuis 4 ans et je peux dire que je peux compter sur une main le nombre de fois où j'ai créé une classe finale (scellée).Une autre règle ici est que je devrais toujours avoir une bonne raison de sceller une classe, plutôt que de la sceller par défaut.

Autres conseils

Pour .NET, vous pouvez utiliser quelque chose comme TypeMock, qui utilise l'API de profilage et vous permet de vous connecter à des appels vers presque tout.

Je crois que Taupes, de Microsoft Research, vous permet de le faire.Depuis la page Taupes :

Les taupes peuvent être utilisées pour détourner toute méthode .NET, y compris les méthodes non virtuelles / statiques dans des types scellés.

MISE À JOUR: il existe un nouveau framework appelé "Fakes" dans la prochaine version de VS 11, conçu pour remplacer Moles :

Le Cadre de faux dans Visual Studio 11 est la prochaine génération de Moles & Stubs, et finira par la remplacer.Cependant, les Fakes sont différents des Moles, donc passer des Moles aux Fakes nécessitera quelques modifications de votre code.Un guide pour cette migration sera disponible ultérieurement.

Exigences:Visual Studio 11 Ultime, .NET 4.5

Le problème avec TypeMock est qu’il excuse une mauvaise conception.Maintenant, je sais que c'est souvent quelqu'un d'autre mauvaise conception qu'il cache, mais l'autoriser dans votre processus de développement peut conduire très facilement à autoriser vos propres mauvaises conceptions.

Je pense que si vous envisagez d'utiliser un framework moqueur, vous devriez en utiliser un traditionnel (comme Moq) et créer une couche d'isolation autour de la chose non moquable, et vous moquer de la couche d'isolation à la place.

J'évite presque toujours d'avoir des dépendances sur des classes externes au plus profond de mon code.Au lieu de cela, je préfère de loin utiliser un adaptateur/pont pour leur parler.De cette façon, je gère ma sémantique et la douleur de la traduction est isolée dans un seul cours.

Cela facilite également le changement de mes dépendances à long terme.

J'ai rencontré ce problème récemment et après avoir lu/recherché sur le Web, il semble qu'il n'y ait pas de solution simple, sauf d'utiliser un autre outil comme mentionné ci-dessus.Ou grossièrement gérer les choses comme je l'ai fait :

  • Créez une instance de classe scellée sans appeler le constructeur.
  • System.Runtime.Serialization.FormatterServices.GetUninitializedObject(instanceType);

  • Attribuez des valeurs à vos propriétés/champs via la réflexion

  • YourObject.GetType().GetProperty("PropertyName").SetValue(dto, newValue, null);
  • YourObject.GetType().GetField("FieldName").SetValue(dto, newValue);

Je prends généralement la voie de la création d'une interface et d'une classe d'adaptateur/proxy pour faciliter la moquerie du type scellé.Cependant, j'ai également expérimenté en ignorant la création de l'interface et en rendant le type de proxy non scellé avec des méthodes virtuelles.Cela a bien fonctionné lorsque le proxy est en réalité une classe de base naturelle qui encapsule et utilise une partie de la classe scellée.

Lorsqu'il s'agissait de code nécessitant cette adaptation, j'en avais assez d'effectuer les mêmes actions pour créer l'interface et le type de proxy, j'ai donc implémenté une bibliothèque pour automatiser la tâche.

Le code est un peu plus sophistiqué que l'exemple donné dans l'article auquel vous faites référence, car il produit un assembly (au lieu du code source), permet d'effectuer la génération de code sur n'importe quel type et ne nécessite pas autant de configuration.

Pour plus d'informations, veuillez vous référer à cette page.

Il est parfaitement raisonnable de se moquer d’une classe scellée car de nombreuses classes framework sont scellées.

Dans mon cas, j'essaie de me moquer de la classe MessageQueue de .Net afin de pouvoir utiliser ma logique de gestion gracieuse des exceptions.

Si quelqu'un a des idées sur la façon de surmonter l'erreur de Moq concernant "Configuration invalide sur un membre non modifiable", faites-le-moi savoir.

code:

    [TestMethod]
    public void Test()
    {
        Queue<Message> messages = new Queue<Message>();
        Action<Message> sendDelegate = msg => messages.Enqueue(msg);
        Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate =
            (v1, v2) =>
            {
                throw new Exception("Test Exception to simulate a failed queue read.");
            };

        MessageQueue mockQueue = QueueMonitorHelper.MockQueue(sendDelegate, receiveDelegate).Object;
    }
    public static Mock<MessageQueue> MockQueue
                (Action<Message> sendDelegate, Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate)
    {
        Mock<MessageQueue> mockQueue = new Mock<MessageQueue>(MockBehavior.Strict);

        Expression<Action<MessageQueue>> sendMock = (msmq) => msmq.Send(It.IsAny<Message>()); //message => messages.Enqueue(message);
        mockQueue.Setup(sendMock).Callback<Message>(sendDelegate);

        Expression<Func<MessageQueue, Message>> receiveMock = (msmq) => msmq.Receive(It.IsAny<TimeSpan>(), It.IsAny<MessageQueueTransaction>());
        mockQueue.Setup(receiveMock).Returns<TimeSpan, MessageQueueTransaction>(receiveDelegate);

        return mockQueue;
    }

Bien qu'il ne soit actuellement disponible qu'en version bêta, je pense qu'il vaut la peine de garder à l'esprit le cale caractéristique du nouveau Cadre de faux (partie de la Visual Studio 11 version bêta).

Les types Shim fournissent un mécanisme pour détourner n’importe quelle méthode .NET vers un délégué défini par l’utilisateur.Les types shim sont générés par le code par le générateur Fakes et utilisent des délégués, que nous appelons types shim, pour spécifier les nouvelles implémentations de méthodes.Sous le capot, les types shim utilisent des rappels qui ont été injectés au moment de l'exécution dans les corps de méthode MSIL.

Personnellement, je cherchais à utiliser ceci pour me moquer des méthodes sur les classes de framework scellées telles que DrawingContext.

Existe-t-il un moyen d'implémenter une classe scellée à partir d'une interface...et se moquer de l'interface à la place ?

Quelque chose en moi pense qu'avoir des cours scellés est une mauvaise chose en premier lieu, mais ce n'est que moi :)

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