Domanda

In che modo le persone si avvicinano a deridere TcpClient (o cose come TcpClient)?

Ho un servizio che accetta un TcpClient. Dovrei avvolgerlo in qualcos'altro più beffardo? Come dovrei affrontarlo?

È stato utile?

Soluzione

Quando si arriva a classi simulate che non sono test-friendly (cioè sigillate / che non implementano alcuna interfaccia / metodi non sono virtuali), probabilmente si vorrebbe usare Adapter modello di progettazione.

In questo modello aggiungi una classe di wrapping che implementa un'interfaccia. Dovresti quindi deridere l'interfaccia e assicurarti che tutto il tuo codice usi quell'interfaccia invece della classe concreta ostile. Sarebbe simile a questo:

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

Altri suggerimenti

Penso che @Hitchhiker sia sulla buona strada, ma mi piace anche pensare di astrarre cose del genere solo un passo avanti.

Non deriderei direttamente TcpClient, perché ciò ti legherebbe ancora troppo strettamente all'implementazione sottostante anche se hai scritto dei test. Cioè, l'implementazione è legata specificamente a un metodo TcpClient. Personalmente, proverei qualcosa del genere:

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

Questa implementazione ti separerà del tutto dai dettagli relativi a Tcp (se questo è un obiettivo di progettazione) e puoi persino inserire input di test da un set di valori codificato o un file di input di test. Molto utile se sei sulla strada per testare il tuo codice per il lungo raggio.

L'uso del modello Adapter è sicuramente l'approccio TDD standard al problema. Tuttavia, è possibile anche creare l'altra estremità della connessione TCP e fare in modo che il proprio cablaggio di prova lo guidi.

L'utilizzo diffuso della classe di adattatori IMO offusca le parti più importanti di un progetto e tende anche a rimuovere molte cose dai test che dovrebbero essere testati nel contesto. Quindi l'alternativa è costruire il tuo ponteggio di prova per includere più del sistema in prova. Se stai costruendo i tuoi test da zero, otterrai comunque la capacità di isolare la causa di un errore in una determinata classe o funzione, semplicemente non sarà in isolamento ...

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