Mocking System.IO.Ports.SerialPort

573 views
Skip to first unread message

wainwrightwt

unread,
Apr 30, 2009, 3:18:21 PM4/30/09
to Rhino.Mocks
I have been attempting to mock the SerialPort class to no avail.
Anytime the .Open() method is called, I get an error stating:

exception: System.IO.IOException: The port 'COM1' does not exist..

It's like the mock object is not being used. I'm assuming it's because
SerialPort is not an interface, and the real methods are actually
being called. But, Rhino Mocks is supposed to be able to mock classes
just fine. I have tried using regular mocks and stubs. Has anyone
attempted this, or know what I should try?

Thanks

Shane Courtrille

unread,
Apr 30, 2009, 3:27:59 PM4/30/09
to Rhino...@googlegroups.com
Rhino Mocks can mock virtual methods just fine...

wainwrightwt

unread,
Apr 30, 2009, 3:35:17 PM4/30/09
to Rhino.Mocks
Understoon, but SerialPort.Open() is not a virtual method. Here is my
code...

[TestMethod]
public void TestMethod1()
{
MockRepository mocks = new MockRepository();
SerialPort sp = mocks.Stub<SerialPort>();
using (mocks.Record())
{
sp.Open();
LastCall.Repeat.Any();
}
mocks.ReplayAll();
sp.Open();
mocks.VerifyAll();
}

The first 'sp.Open()' inside the Record section is failing.

On Apr 30, 3:27 pm, Shane Courtrille <shanecourtri...@gmail.com>
wrote:
> Rhino Mocks can mock virtual methods just fine...
>

Shane Courtrille

unread,
Apr 30, 2009, 3:41:38 PM4/30/09
to Rhino...@googlegroups.com
If the method is not virtual then Rhino Mocks can't mock it.

In that case you have two choices.  Use something else like TypeMock or preferably create your own wrapper around the serial port stuff. 

From an architectural point of view it's a good practice to wrap components you don't have complete control over.  More important then the testing aspect is that you aren't coupling your code to any one vendor or product.  If a few weeks down the rode you realize you need the power of a 3rd party serial port control you only have to create a new wrapper instead of going through your code and modifying everywhere that deals with serial ports. 

wainwrightwt

unread,
Apr 30, 2009, 4:18:20 PM4/30/09
to Rhino.Mocks
Thanks,

But, we are actually wrapping the SerailPort object. It is the wrapper
that I would like to test. We have a "COMBuffer" class which uses the
SerialPort object. But, in order to test the COMBuffer wrapper class,
I want to mock the SerialPort class so that it would not attempt to
connect to a real serialport.

example COMBuffer method:

public void SetupSerialPort(string p_PortName, int p_BaudRate, Parity
p_Parity,
int p_DataBits, StopBits
p_StopBits, Handshake p_Handshake,
int p_ReadTimeoutMS, int
p_WriteTimeoutMS, SerialPort m_SerialPort)
{
if (string.IsNullOrEmpty(p_PortName) ||
p_BaudRate == 0 ||
p_DataBits == 0)
{
throw new ArgumentException("Invalid value passed into
Setup");
}

if (m_SerialPort == null)
{
m_SerialPort = new SerialPort()
}

m_SerialPort.PortName = p_PortName;
m_SerialPort.BaudRate = p_BaudRate;
m_SerialPort.Parity = p_Parity;
m_SerialPort.DataBits = p_DataBits;
m_SerialPort.StopBits = p_StopBits;

//Default is Handshake.None. Only change if not
Handshake.None.
if (p_Handshake != Handshake.None)
{
m_SerialPort.Handshake = p_Handshake;
}

m_ReadOperationIntervalMS = m_ReadWaitTimeMS =
p_ReadTimeoutMS;
m_WriteOperationIntervalMS = m_WriteWaitTimeMS =
p_WriteTimeoutMS;

m_SerialPort.DataReceived += new
SerialDataReceivedEventHandler(PortDataReceived);

m_SerialPort.Open();
m_SerialPort.DiscardInBuffer();
m_SerialPort.DiscardOutBuffer();
}

This is just one example, there are many more methods that I would
like to test that use the SerialPort. So, is it possible to test a
method that uses the SerialPort object?

Thanks

On Apr 30, 3:41 pm, Shane Courtrille <shanecourtri...@gmail.com>
wrote:
> If the method is not virtual then Rhino Mocks can't mock it.
>
> In that case you have two choices.  Use something else like TypeMock or
> preferably create your own wrapper around the serial port stuff.
>
> From an architectural point of view it's a good practice to wrap components
> you don't have complete control over.  More important then the testing
> aspect is that you aren't coupling your code to any one vendor or product.
> If a few weeks down the rode you realize you need the power of a 3rd party
> serial port control you only have to create a new wrapper instead of going
> through your code and modifying everywhere that deals with serial ports.
>

Shane Courtrille

unread,
Apr 30, 2009, 4:38:48 PM4/30/09
to Rhino...@googlegroups.com
Ohhh.

My personal view is that if I'm testing a wrapper I always test it against the real thing.  This can be a pain in the butt but I don't see much value in mocking things out in this case (which you could do with TypeMock). 

In your case testing against a real serial port might be quite difficult (I don't know.. never worked with physical devices like that).  In that case one option would be to create a super thin wrapper which has the exact same interface as a Serial Port object and only does pass through.  You could mock that out quite easily then.

Tom Opgenorth

unread,
Apr 30, 2009, 6:06:18 PM4/30/09
to Rhino...@googlegroups.com
+1 to what Shane is saying. A while back I had the exact problem as
this. The strategy I picked was to make a slimmed down interface that
had ONLY the methods/properties from SerialPort, and make that a thin
wrapper around that. My application then used that wrapper class,
which was now easy to mock out.

I made sure that I had functional tests that would exercise my
wrapper. I'd setup virtual serial ports using com0com, and have my
wrapper use those in the functional tests.

It was a bit of a PITA, but it worked.

HTH
--
http://www.opgenorth.net

wainwrightwt

unread,
May 1, 2009, 10:55:02 PM5/1/09
to Rhino.Mocks
Thanks for the info. We are also using com0com, and will now most
likely go down the "thin" wrapper path. This seems to be the easiest
solution. Again, thanks.

On Apr 30, 6:06 pm, Tom Opgenorth <opgeno...@gmail.com> wrote:
> +1 to what Shane is saying.  A while back I had the exact problem as
> this.  The strategy I picked was to make a slimmed down interface that
> had ONLY the methods/properties from SerialPort, and make that a thin
> wrapper around that.  My application then used that wrapper class,
> which was now easy to mock out.
>
> I made sure that I had functional tests that would exercise my
> wrapper.  I'd setup virtual serial ports using com0com, and have my
> wrapper use those in the functional tests.
>
> It was a bit of a PITA, but it worked.
>
> HTH
>
> On Thu, Apr 30, 2009 at 14:38, Shane Courtrille
>
>
>
>
>
> <shanecourtri...@gmail.com> wrote:
> > Ohhh.
>
> > My personal view is that if I'm testing a wrapper I always test it against
> > the real thing.  This can be a pain in the butt but I don't see much value
> > in mocking things out in this case (which you could do with TypeMock).
>
> > In your case testing against a real serial port might be quite difficult (I
> > don't know.. never worked with physical devices like that).  In that case
> > one option would be to create a super thin wrapper which has the exact same
> > interface as a Serial Port object and only does pass through.  You could
> > mock that out quite easily then.
>
> > On Thu, Apr 30, 2009 at 2:18 PM, wainwrightwt <wainwright.wa...@gmail.com>

Kenneth Xu

unread,
May 3, 2009, 12:06:43 PM5/3/09
to Rhino...@googlegroups.com
You don't actually have to "write" a wrapper, what I usually do is define an interface that contains the methods you want to use, in this case

public interface ISerialPort
{
  void Open();
  // all other method you use from SerialPort
}

public MySerialPort : SerialPort, ISerialPort {}

make the m_SerialPort internal and in you test case

comBuffer.m_SerialPort = mockery.CreateMock<ISerialPort>();

And then you can do your test.

IMHO, a good lib should always expose interface. But fortunately, if there isn't one, you can create yourself. Interface rocks.
Reply all
Reply to author
Forward
0 new messages