how does one Moq a serial port?

1,988 views
Skip to first unread message

gerry_lowry [alliston ontario canada [705] 250-0112]

unread,
Nov 26, 2010, 11:43:19 AM11/26/10
to moq...@googlegroups.com
Please note: assume this serial port is on remote, non attached computer.

Scenario:

I'm writing a c#, .NET 4 program to read and parse data
from a computer that is attached to a non computer device
that does have a specialized "computer" for capturing data.

This data can be downloaded through a serial cable
with a program like Windows HyperTerminal.
A "capture" text file is created for later processing.

I've a separate program that parses the downloaded data from
the specialized "computer".

I want to replace the manual downloading with a c# .NET 4
program that automates the downloading of the serial port data.

Since my development environment is not even connected to the target computer, I need to simulate the transfer
of serial data in order to use TDD and xUnit.net to ensure
as best as possible that my program is robust and as
correct as possible before I actually test it in the "real world"
environment.

I'm wondering how I might use Moq (and/or maybe something else)
for the purpose that I've described above.

Note: serial computing has a number of issues,
random data loss is possible in this particular
situation but the most likely issues may be
related to timing and timeouts; example, a human
might be using the related non computer device while the
specialized "computer" is attempting to
respond to requests via its serial port.

Any ideas would be appreciated.

Thank you.

Regards,
Gerry

David Allen

unread,
Nov 26, 2010, 12:04:40 PM11/26/10
to moq...@googlegroups.com
It is precisely these kinds of situations, where the real
hardware/software are not easily available or tested that mocks are
valuable.

Are you experienced with using mocks in more mundane situations? Do
you have experience with other mocking frameworks or tools? Have you
used TDD before?

I'm trying to understand whether you are asking about mocking and
testing in general or MOQ in particular.
David Kreth Allen


On Fri, Nov 26, 2010 at 10:43 AM, gerry_lowry [alliston ontario canada
[705] 250-0112] <gerry...@abilitybusinesscomputerservices.com>
wrote:

> --
> Post: moq...@googlegroups.com
> Unsubscribe: moqdisc-u...@googlegroups.com

--
David Kreth Allen
http://codecontracts.info

gerry_lowry [alliston ontario canada [705] 250-0112]

unread,
Nov 26, 2010, 12:26:09 PM11/26/10
to moq...@googlegroups.com
Hello David,

I've too little experience with Moq, which I've
chosen because the source is available and because
Moq is written in c# and has had great reviews.

Also, the fact that Daniel chose xUnit.net
to unit test Moq was a strong initial factor
in my looking at Moq versus alternatives.

My use of Moq is very limited to date,
mostly with ASP.NET MVC development.

Perhaps I'm over complicating this?

As described below, serial port data flow
appears to me to be a bit more challenging
because of timing issues that are much less
likely in a RESTful ASP.NET MVC environment.

g.

P.S.: I had done quite a bit of research around Moq
but then was not allowed by my employer at
the time to even use xUnit.net or any unit testing
period in their WebForms environment; for
that reason, I'm quite rusty and busy trying
to "get it" with regards to mocking in general
and Moq in particular.

----- Original Message ----- David Kreth Allen http://codecontracts.info <davidkr...@gmail.com>
To: <moq...@googlegroups.com>
Sent: Friday, November 26, 2010 12:04 PM
Subject: Re: [Moq] how does one Moq a serial port?

__________________________________
Gerry Lowry, Partner http://twitter.com/gerryLowry1947
Alliston � Ontario � Canada � L9R 0E1 � 705.250.0112
gerry...@abilitybusinesscomputerservices.com http://abilitybusinesscomputerservices.com

David Allen

unread,
Nov 26, 2010, 9:04:45 PM11/26/10
to moq...@googlegroups.com
On Fri, Nov 26, 2010 at 11:26 AM, gerry_lowry [alliston ontario canada [705] 250-0112] <gerry...@abilitybusinesscomputerservices.com> wrote:
> Perhaps I'm over complicating this?
We can wish, but I am afraid it is really just complicated <smile>.
 
As far as MOQ goes,  I use MOQ on a regular basis at work and I have been very happy with it. I use it for testing code that is running in both console and MVC web applications. However, your situation with the devices poses some special challenges.
 
First, let's review your architecture to gain a perspective. I imagine you plan to have a system interface layer which is at the boundary of your system, and operates the serial port to poll the external device.  There must be some classes you use to read a serial port. Those are the things you will have to mock. But you cannot mock them unless you understand them.  I took a look at the most likely candidate, the SerialPort class. This poses several challenges:
1) can you mock it?
2) Do you understand how it will behave in the happy path and variant use cases?
 
You cannot use MOQ to mock SerialPort directly. It is a concrete class without virtual methods. I see two ways around this obstacle: either buy TypeMock, which can mock many more things than MOQ can, or you create your own interface ISerialPort and use the adapter pattern to wrap a real serial adapter and implement the interface. Then you can code to the interface, which is the preferred practice anyway, to provide isolation and testability.  Then you can MOQ the interface quite easily. The adapter approach is the one I would use because I would not want to buy TypeMock. Your choice may be different. Either way, this challenge is solved.  If you have any doubts what this looks like, I pasted a simplified version below. It's worthwhile for others to have because this is such a common challenge. And people do not always think to take this approach. They simply say "I can't mock this so I give up."
 
The harder part is understanding how your device will work in practice. You cannot simulate something you do not understand. If you have complete and reliable description of the device under test in all scenarios of interest, and they specify exactly what signals you send, and how data flows, then you are very lucky. More likely, you do not have that. You will have to get access to the real device for an extended period of time. At this point, you have lots of hard choices. But all of them involve playing with the device and learning what it will spit out under different scenarios. I can't imagine any easier way to do it. I'm sure you were expecting to do this anyway, right? As I mentioned above, MOQ can easily mock an interface, no matter how complex. Coping with exception cases like missing data, timeouts, etc... are all easy problems to solve. The hard part of your problem is doing enough coding and testing with the real device to understand it's behavior well enough to simulate it.
 
Best wishes. And let me know your thoughts. The project sounds fascinating. I love hardware. And I'm interested in how you finally deal with these constraints you face.
David Kreth Allen
 
Below is one way to mock things like SerialPort which don't have convenient interfaces. Just create your own and use Adapter pattern to wrap the object that is hard to mock/test.
 
using System.IO.Ports;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
 
namespace SerialPortTests
{
   [TestClass]
   public class UnitTest1
   {
       [TestMethod]
       public void UsingMoqToSimulateSerialPort()
       {
           // Arrange
           Mock<ISerialPort> mockSerialPort = new Mock<ISerialPort>();
           string mockedSerialInput = "Hello I am a happy device.";
           mockSerialPort.Setup(s=>s.ReadLine())
               .Returns(mockedSerialInput);
 
           // Act
           DeviceController controller =
               new DeviceController(mockSerialPort.Object);
           string result = controller.ReadPort();
 
           // Assert
           Assert.AreEqual(mockedSerialInput,result,"expected result");
       }
       [TestMethod]
       public void ExerciseOfTheRealSerialPort()
       {
           // Arrange
           SerialPortAdapter portAdapter = new SerialPortAdapter(new SerialPort());
           string mockedSerialInput = "Hello I am a happy device.";
 
           // Act
           DeviceController controller = new DeviceController(portAdapter);
           string result = controller.ReadPort();
 
           // Assert
           Assert.AreEqual(mockedSerialInput, result, "expected result");
       }
 
   }
   public class DeviceController
   {
       private readonly ISerialPort _serialPort;
       public DeviceController(ISerialPort serialPort)
       {
           this._serialPort = serialPort;
       }
       public string ReadPort()
       {
           return _serialPort.ReadLine();
       }
   }
   public interface ISerialPort
   {
       string ReadLine();
   }
   public class SerialPortAdapter : ISerialPort
   {
       private readonly SerialPort _serialPort;
 
       public SerialPortAdapter(SerialPort serialPort)
       {
           _serialPort = serialPort;
           _serialPort.ReadTimeout = 10;//my serial port is connected to nothing and I get tired of waiting for failure.
       }
 
       virtual public string ReadLine()
       {
           _serialPort.Open();
           string result;
           try
           {
               result = _serialPort.ReadLine();
           }
           finally
           {
            _serialPort.Close();              
           }
           return result;
       }
   }
}
 

gerry_lowry [alliston ontario canada [705] 250-0112]

unread,
Dec 1, 2010, 4:57:10 PM12/1/10
to moq...@googlegroups.com
Thank you David.
You've put so much thought into your answer that you've thrilled me.
g.

P.S.: more comments below.

-- edited ---- Original Message ----- From: David Allen To: moq...@googlegroups.com
Sent: Friday, November 26, 2010 9:04 PM Subject: Re: [Moq] how does one Moq a serial port?

On Fri, Nov 26, 2010 at 11:26 AM, gerry_lowry [alliston ontario canada [705] 250-0112] wrote:
> Perhaps I'm over complicating this?
We can wish, but I am afraid it is really just complicated <smile>.

[snip]


your situation with the devices poses some special challenges.

{g.} which is why I'm grateful for your answer.

... architecture ... perspective.


a system interface layer which is at the boundary of your system, and
operates the serial port to poll the external device.

{g.} it must both send and listen
{g.} example text commands and sample responses:
{g.} >show time
{g.} 10:21 DEC 1, 2010
{g.} >show transaction summary
{g.} 246/1000 USED
{g.} >show transactions
{g.} stream of data ending with prompt
{g.} line 1 of transaction 1
{g.} line n of transaction 1
{g.}
{g.} line 1 of transaction n
{g.} line n of transaction n
{g.} 246/1000 USED
{g.} >enter privileged mode
{g.} PASSWORD ?:
{g.} et cetera

... some classes you use to read a serial port. ... you will have to mock.
...I took a look at the most likely candidate, the SerialPort class. This poses several challenges:


1) can you mock it?
2) Do you understand how it will behave in the happy path and variant use cases?

{g.} yes, from doing this manually via HyperTerminal two or more times
{g.} per month for a few years;
{g.} nevertheless, I just replaced a Perl script with an almost
{g.} complete c# class and in the process discovered that
{g.} my original Perl script has a serious flaw that I did not
{g.} discover because my sample data was too small to
{g.} reveal an exception case.

... I see two ways around this obstacle:
either buy TypeMock, ...or


you create your own interface ISerialPort

[snip]


The adapter approach is the one I would use because I would not want to buy TypeMock.
Your choice may be different.

{g.} same choice as yours for three reasons:
{g.} (a) really like Moq
{g.} (b) could spend my entire life learning new tools
{g.} and never write a line of code
{g.} (c) money is really tight at the moment

...I pasted a simplified version below.

It's worthwhile for others to have because this is such a common challenge.

{g.} I'm certain others while appreciate your effort also; again, thank you.
[snip]


You will have to get access to the real device for an extended period of time.

{g.} fortunately, this is possible.
... lots of hard choices. ... all of them involve playing with the device ...


I'm sure you were expecting to do this anyway, right?

{g.} yes
... let me know your thoughts.
{g.} definitely, I will once I've sorted them out;
{g.} I need to study your approach; your ideas
{g.} will get me headed in the right direction.
[snip]

David Allen

unread,
Dec 1, 2010, 5:58:57 PM12/1/10
to moq...@googlegroups.com
you're welcome. Your problem looks like one of those that will be hard to figure out, but very satisfying when you have accomplished it!

On Wed, Dec 1, 2010 at 3:57 PM, gerry_lowry [alliston ontario canada [705] 250-0112] <gerry...@abilitybusinesscomputerservices.com> wrote:
Thank you David.

Reply all
Reply to author
Forward
0 new messages