1

I am working on a large legacy java application. It already has an extensive existing framework in place for handling device drivers. I need to create a new device driver for a device that connects to a serial port via JavaComm.

The existing drivers simply create the new serial port inside their configure() methods, then create new input and output streams from the serial port object, then use those input and output streams for the device comms, but with no unit tests.

I want my new class to be unit testable however, but not sure how I can do that if it's going to fit in with this existing framework that will expect the serial port, input and output streams to be set up in the configure() method.

Any ideas?


    public void configure()
    {
        super.configure();

        if (isEmulated()) {
            return;
        }
        if (isFaulty()) {           
            if (isOutOfService()) {
                ZBopNotificationManager.getInstance().add(
                        new SystemNotice(SeverityCode.LEVEL3, getName(), getErrorMessage()));
            }
            return;         
         }

        // ZP:
        String portName = getSerialPort();
        // String portName = "COM1";
        try {
            CommPortIdentifier id = CommPortIdentifier.getPortIdentifier(portName);
            Trace.log(this, Trace.D, "Port name = " + id.getName());
            port = (SerialPort) id.open(getName(), 1000);
        } catch (NoSuchPortException nspe) {
            report(SeverityCode.LEVEL3, getName(), "Bar Code Scanner is not connected to " + portName + " port, or the port does not exist.");
            return;
        } catch (PortInUseException piue) {
            report(SeverityCode.LEVEL3, getName(), portName + " port is already in-use by some other device. Reason: " + piue.getMessage());
            return;
        }

        try {
            port.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
        } catch (UnsupportedCommOperationException e) {
            // this should not happen
            port.close();
            report(SeverityCode.LEVEL2, getName(), portName + " port configuration failed: " + e);
            return;
        }

        try {
            in = port.getInputStream();
            out = port.getOutputStream();
        } catch (IOException ioe) {
            port.close();
            report(SeverityCode.LEVEL3, getName(), portName + " port configuration failed: " + ioe.getMessage());
            return;
        }
meout(30);

        // ... other init code omitted
    }


Wim Coenen
  • 66,094
  • 13
  • 157
  • 251
fred basset
  • 9,774
  • 28
  • 88
  • 138

2 Answers2

3

By the looks of things, the javax.comm API doesn't make life easy for unit tests - it's big on classes, and light on interfaces.

My suggest would be to create interfaces and adaptor classes for each javax.comm class that you need to use in your driver. Your driver code would then talk to those interfaces, rather than directly to javax.comm. You probably only need a subset of the API anyway, and defining these interfaces should help you clarify your design.

This will allow you to use mock implementations of those interfaces in your unit tests (e.g. JMock, Mockito, etc). Your unit test can inject these mocks into the driver object.

When used for real, the driver's configure() method can instantiate the adaptor classes rather than the mocks.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • I almost understand. configure() still needs to create the adapter that creates the real object to use and my unit test needs to call configure() to simulate the bring up of the device. So I'm sill then back at my original problem of having the dependancy on the real serial port? That part I do not understand, how to unit test configure() and have it still work with the real port in production code. – fred basset Feb 26 '11 at 21:10
  • @fred: Your unit test would *not* call `configure()`, it would inject the mocks directly into the object (e.g. using setter methods). Only the runtime framework would call `configure()`, and that would create the adaptor objects, not mocks. – skaffman Feb 26 '11 at 21:19
1

If i understood you correctly you want to test devicedriver and not a module that uses the device driver.

Is it ok to have an integrationtest instead of a unittest? If you connect the serial port-s rxdata with the txdatapin and the rts with the cts pin then the integration test can check that every thing send into outputstream should be received by the inputstream.

k3b
  • 14,517
  • 7
  • 53
  • 85