I'm unit testing a class that talks to a hardware device through a serial port. I created an interface to isolate the SerialPort
class in System.IO:
public interface ISerialPort
{
String PortName { get; set; }
bool IsOpen { get; }
void Open();
void Close();
int Read(byte[] buffer, int offset, int count);
void Write(byte[] buffer, int offset, int count);
}
There's a function in my class under test that calls Read
, and checks for specific values. For example:
public bool IsDevicePresent()
{
byte[] buffer = new byte[3];
int count = 0;
try
{
port.Write(new byte[] { 0x5A, 0x01 }, 0, 2);
count = port.Read(buffer, 0, 3);
}
catch (TimeoutException)
{
return false;
}
return (buffer[0] == 0x07 && count == 3);
}
port
is an instance of ISerialPort
.
I'm trying to write some tests for the IsDevicePresent
function, using Moq to mock an ISerialPort
. However, I can't figure out how to get Moq to set values in the passed byte array (buffer
). I can get Moq to return 3, but how can I get Moq to set the first byte in buffer
to 0x07?
var mock = new Mock<ISerialPort>();
mock.Setup(m => m.Read(It.IsAny<byte[]>(), It.IsAny<int>(),It.IsAny<int>()))
.Returns(3);
You can use the Callback
method to access the incoming parameters and set first element of the passed in buffer:
mock.Setup(m => m.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()))
.Returns(3)
.Callback<byte[], int, int>((buffer, offset, count) => { buffer[0] = 0x07; });
You can do the same thing inside the Returns
mock.Setup(m => m.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()))
.Returns<byte[], int, int>((buffer, offset, count) =>
{
buffer[0] = 0x07;
return 3;
});
But using the Callback
is more easier to follow than making the side-effect inside the Returns
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With