mainvoid
mainvoid

Reputation: 357

How should unit tests be written for a "send-receive" method?

How shoud unit tests be written for a method that performs a send-recieve operation in orther to communicate with a generic device?

In the following example, in order to query a serial device (MyDevice.Read method) a string formatted in a specific way is sent to the device and the device responds with a specific string according to the message sent.

This is the interface needed to mock the serial port:

public interface ISerialPort
{
    void WriteLine(string text);

    void ReadLine(string text);
}

This is the client class that uses the interface:

public class MyDevice
{
    private ISerialPort _port;

    public MyDevice(ISerialPort port)
    {
        _port = port;
    }

    public DeviceResponse Read(...)
    {
        _port.WriteLine(...);

        string response = _port.ReadLine();

        // Parse the response.
        return new DeviceResponse(response);
    }
}

And this are the unit tests for the Read method (failing/exception tests are left out on purpose) that I would write:

[TestClass]
public class MyDeviceTests
{
    [TestMethod]
    public void Read_CheckWriteLineIsCalledWithAppropriateString()
    {
        Mock<ISerialPort> port = new Mock<ISerialPort>();

        MyDevice device = new MyDevice(port.Object);

        device.Read(...);

        port.Verify(p => p.WriteLine("SpecificString"));
    }

    [TestMethod]
    public void Read_DeviceRespondsCorrectly()
    {
        Mock<ISerialPort> port = new Mock<ISerialPort>();

        MyDevice device = new MyDevice(port.Object);

        port.Setup(p => p.ReadLine()).Returns("SomeStringFromDevice");

        DeviceResponse response = device.Read(...);  

        // Asserts here...
    }

    ...
}

Another doubt: Is it correct to write a test just to check if a method should be called with specific arguments?

Upvotes: 2

Views: 658

Answers (1)

Dror Helper
Dror Helper

Reputation: 30820

This is a good way to "unit test" such a device. Unless you want to connect a real device or simulated one.

You should keep each test simple and to the point - i.e. when testing read return the expected string (and nothing else) and check the system behavior, when writing verify that write was called with the exact string.

Upvotes: 1

Related Questions