2016-06-29 9 views
2

Ich bin neu in der Informatik und habe wenig Wissen im Netzwerk. Ich habe eine Aufgabe in meinem Praktikum.Es soll einen TCPClient mit Interface implementieren. Die Idee ist, dass wir, da wir keine Verbindung zum echten Server herstellen müssen, nur einen Schein-TCPClient benötigen, um Daten zu empfangen, zu speichern und zu versenden. Von was ich verstehe, ist es nur die sendmessage Funktion in TCPClient zu verspotten ??Wie man TCPClient durch Implementierung der Schnittstelle Mock

public interface ITCPClient 
{ 
    /// <summary> 
    /// Event handler when TCP client is connected 
    /// </summary> 
    event ConnectionEventHandler Connected; 

    /// <summary> 
    /// Event handler for TCP Client on receiving data 
    /// </summary> 
    event DataReceivedEventHandler DataReceived; 

    /// <summary> 
    /// Event handler when TCP client is disconnect 
    /// </summary> 
    event ConnectionEventHandler Disconnected; 

    /// <summary> 
    /// Reports error when an error occurs 
    /// </summary> 
    event ErrorEventHandler OnError; 

    /// <summary> 
    /// Set whether to use HostByteOrder or NetworkByteorder with the socket - gateway expects network byte order 
    /// </summary> 
    bool ByteOrder { get; set; } 

    /// <summary> 
    /// Returns true if the client is running and connected to the server 
    /// </summary> 
    bool IsRunning { get; } 

    /// <summary> 
    /// Add the message to the sendqueue. The message will be processed by the ProcessMessage function waiting for the message. 
    /// </summary> 
    /// <param name="Message"></param> 
    void SendMessage(string Message); 

    /// <summary> 
    /// Add the message to the sendqueue. The message willbe processed by the ProcessMessage function waiting for the message. 
    /// </summary> 
    /// <param name="Message"></param> 
    void SendMessageHiPriority(string Message); 

    /// <summary> 
    /// Starts the client and spawn the thread for processing the message 
    /// </summary> 
    void Start(); 

    /// <summary> 
    /// Disconnects and stops listening for messages 
    /// </summary> 
    void StopProcessing(); 

} 

public class MockTCPClient : ITCPClient 
{ 
    #region Private Fields 

    private string msg; 

    #endregion Private Fields 


    #region Constructor 

    public MockTCPClient() 
    { 
     //nothing 
    } 


    #endregion Constructor 

    #region event 

    public event ConnectionEventHandler Connected; 
    public event ConnectionEventHandler Disconnected; 
    public event ErrorEventHandler OnError; 
    public event DataReceivedEventHandler DataReceived; 

    #endregion event 

    #region property 
    //question 
    public string ReceivedMessage 
    { 
     get 
     { 
      return msg; 
     } 

     set 
     { 
      msg = value; 
     } 

    } 

    #endregion property 

    //question?? 
    private void OnDataReceived(object sender, string e) 
    { 
     DataReceivedEventHandler dataReceived = DataReceived; 
     if (dataReceived != null) 
      dataReceived(this, e); 
    } 


    #region ITCPClient Members 
    #region properties 

    public bool ByteOrder { get; set; } 


    public bool IsRunning { get; } 

    #endregion properties 

    public void SendMessage(string Message) 
    { 
     msg = Message; 
    } 

    public void SendMessageHiPriority(string Message) 
    {  
    } 

    public void Start() 
    { 
    } 


    public void StopProcessing() 
    { 
    } 


    #endregion ITCPClient Members 

} 
+0

Sie können ein Mock Framework verwenden, anstatt die gesamte Schnittstelle implementieren zu müssen. Sie konfigurieren nur die Teile, die Sie für Ihren Test benötigen, und Sie sind fertig. lesen Sie auf Moq, NSubstitute und es gibt ein paar mehr. Ich würde auch empfehlen, zu lesen, wie ein TcpClient funktioniert, damit Sie eine Vorstellung davon haben, was Sie zum Nachahmen brauchen. – Nkosi

+0

Können Sie klären, mit welchen Methoden und Eigenschaften von ITCPClient Ihre Klasse interagieren muss? –

+0

@ScottHannen Ja.Die Methode ist void SendMessage (string Message); Und ich denke auch Ereignis DataReceivedEventHandler DataReceived wird ebenfalls berücksichtigt. Aber ich habe keine Ahnung, wie man ein Event in C# implementiert. Die Methode SendMessage wird verwendet, um Nachrichten in einer Warteschlange in die Warteschlange einzureihen, die im ursprünglichen TCPClient verarbeitet werden. Ich bin mir nicht sicher, ob ich meine Frage klar erkläre. Vielen Dank! – lancwl

Antwort

1

Dies zeigt, wie Moq überprüfen kann, ob Ihre Klasse eine seiner Methoden aufruft.

Dieser Test
- erstellt ein Modell von ITCPClient
- gibt an, dass die SendMessage Verfahren nachprüfbar sind - mit anderen Worten, wird seine Verwendung verfolgt werden.
- überprüft, ob SendMessage("test"); für das verspottete Objekt aufgerufen wurde.

Der Test wird fehlschlagen, weil es nie SendMessage("test");

[TestMethod] 
public void TestTcpClient() 
{ 
    var mockedTcpClient = new Mock<ITCPClient>(); 
    mockedTcpClient.Setup(x => x.SendMessage(It.IsAny<string>())).Verifiable(); 
    //mockedTcpClient.Object.SendMessage("test"); 
    mockedTcpClient.Verify(x=>x.SendMessage("test")); 
} 

ruft Wenn wir die Zeile Kommentar-, die SendMessage("test") dann wird der Test passieren nennt.

Also in "echten" Verwendung würden Sie die Mock erstellen und verwenden Sie es anstelle einer ITCPClient beim Testen der Klasse, die davon abhängt. Wenn es fertig ist, können Sie Verify, dass Ihre Klasse SendMessage genannt und den erwarteten Wert übergeben.

Wenn Sie nicht Moq verwenden, hier ist ein völlig anderer Ansatz:

Erstellen Sie eine Klasse, die ITCPClient wie folgt implementiert. Sie können die meisten Methoden leer lassen und implementieren nur SendMessage zusammen mit ein paar anderen Details:

public class TcpClientMock : ITCPClient 
{ 
    private readonly List<string> _sentMessages; 

    public TcpClientMock(List<string> sentMessages) 
    { 
     _sentMessages = sentMessages; 
    } 

    public void SendMessage(string Message) 
    { 
     _sentMessages.Add(Message); 
    } 

    //rest of non-implemented methods 
} 

In Ihrem Gerät zu testen, dies zu tun:

var sentMessages = new List<string>(); 
var mockedTcpClient = new TcpClientMock(sentMessages); 

Dann schaffen, was Klasse du gehst zu teste und handle darauf. Wenn es fertig ist, sehen Sie, ob sentMessages die Nachricht enthält, die Sie erwarten.


Wie zum Empfangen von Daten, nehme ich an Sie, dass die Veranstaltung würde müssen, um Ihr verspottet Objekt sagen zu erhöhen, so dass Sie, dass Ihre Klasse reagiert wie erwartet überprüfen konnte, wenn das Ereignis ausgelöst wird. Sie könnten eine Methode TcpClientMock wie folgt hinzu:

public void SimulateDataReceived(object sender, DataReceivedEventHandlerArgs args) 
{ 
    DataReceived(sender, args); 
} 

Auf diese Weise, wenn Sie Ihre Klasse eingerichtet haben, die auf ITCPClient ab, die Sie SimulateDataReceived auf dem Mock nennen kann, verursacht es das Ereignis zu erhöhen, was wiederum veranlassen Sie Ihr Testobjekt zu antworten.

+0

Es sieht sehr klar aus und ich denke, ich habe die Grundidee! Vielen Dank für Ihre Antwort! Und noch eine Frage. Muss ich für den Komponententest auch die SimulateDataReceived-Methode testen? – lancwl

+0

Wenn Sie eine andere Frage haben, starten Sie eine andere Frage, anstatt die Kommentare zu verwenden. Wenn dies korrekt ist, sollten Sie es als Antwort markieren. Dies hilft anderen Benutzern, die ähnliche Probleme haben können und vergibt auch den Benutzer, der einige Reputation beantwortet. Deine Frage wurde gut geschrieben, also bekam sie eine Verbesserung :) –

+0

Du brauchst 'SimulateDataReceived' nicht zu testen, weil diese Klasse selbst nur ein Mock ist. Mit dieser Methode könnten Sie simulieren, ein 'DataReceived'-Ereignis auszulösen. Aber wenn das nicht etwas ist, was Sie simulieren müssen, dann können Sie das völlig ignorieren. –