Question

Comment les gens abordent-ils le moquage de TcpClient (ou des choses comme TcpClient)?

J'ai un service qui prend un TcpClient. Dois-je envelopper cela dans quelque chose d'autre plus moquable? Comment dois-je aborder cela?

Était-ce utile?

La solution

Lorsque vous venez de simuler des classes qui ne sont pas conviviales pour les tests (c'est-à-dire que les interfaces scellées / n'implémentant aucune interface / méthode ne sont pas virtuelles), vous voudrez probablement utiliser modèle de conception de l'adaptateur .

Dans ce modèle, vous ajoutez une classe d'habillage qui implémente une interface. Vous devez alors vous moquer de l'interface et vous assurer que tout votre code utilise cette interface au lieu de la classe concrète inamicale. Cela ressemblerait à quelque chose comme ça:

public interface ITcpClient
{
   Stream GetStream(); 
   // Anything you need here       
}
public class TcpClientAdapter: ITcpClient
{
   private TcpClient wrappedClient;
   public TcpClientAdapter(TcpClient client)
   {
    wrappedClient = client;
   }

   public Stream GetStream()
   {
     return wrappedClient.GetStream();
   }
}

Autres conseils

Je pense que @Hitchhiker est sur la bonne voie, mais j'aime aussi penser à résumer des choses comme ça, juste un peu plus loin.

Je ne me maquillerais pas directement avec TcpClient, car cela vous lierait quand même trop étroitement à l'implémentation sous-jacente, même si vous avez écrit des tests. En d’autres termes, votre implémentation est liée à une méthode TcpClient en particulier. Personnellement, je voudrais essayer quelque chose comme ça:

   [Test]
    public void TestInput(){

       NetworkInputSource mockInput = mocks.CreateMock<NetworkInputSource>();
       Consumer c = new Consumer(mockInput);

       c.ReadAll();
    //   c.Read();
    //   c.ReadLine();

    }

    public class TcpClientAdapter : NetworkInputSource
    {
       private TcpClient _client;
       public string ReadAll()
       { 
           return new StreamReader(_tcpClient.GetStream()).ReadToEnd();
       }

       public string Read() { ... }
       public string ReadLine() { ... }
    }

    public interface NetworkInputSource
    {
       public string ReadAll(); 
       public string Read();
       public string ReadLine();
    }

Cette implémentation vous dissociera complètement des détails liés à TCP (s’il s’agit d’un objectif de conception), et vous pouvez même rediriger une entrée de test à partir d’un ensemble de valeurs codé en dur, ou d’un fichier d’entrée de test. Très utile si vous êtes sur la route pour tester votre code sur le long terme.

L’utilisation du modèle d’adaptateur est très certainement l’approche TDD standard du problème. Cependant, vous pouvez également simplement créer l’autre extrémité de la connexion TCP et laisser votre test harnais le piloter.

IMO, l'utilisation répandue de la classe adaptateur obscurcit les parties les plus importantes d'une conception et tend également à supprimer de nombreux éléments à tester qui doivent réellement être testés dans leur contexte. L'alternative consiste donc à développer votre échafaudage de test pour inclure davantage de systèmes à tester. Si vous construisez vos tests à partir de la base, vous obtiendrez tout de même la possibilité d’isoler la cause d’un échec pour une classe ou une fonction donnée, cela ne sera tout simplement pas isolé ...

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