views:

218

answers:

2

Hi,

In reference to an earlier question of mine link text, I have been searching for good ways to write code that is very dependant on 3d party libraries, but still unit-testable.

Just to sketch the contest (so you don't have to read the previous post), I am writing code with the AutoCAD API. This way my code is very dependant on that API, and even worse, AutoCAD requires the code to be running inside AutoCAD context, otherwise there are Licensing exceptions. This causes unit testing with the AutoCAD API as being a no-no.

Now, I'm wondering if using the Adapter Pattern for this would be a nice work-around? This way I could work with my own adapter classes and unit test that functionality.

Would this be a possible implentation of the adapter pattern and would this be a good idea? Are there things I'm overlooking?

Any other suggestions, all is welcome

edit:

  • as Gerrie suggested, wrapping the acad classes could be a route to go. Because the API is not as straight-forward, we already are wrapping a lot of the acad functionality. This way we can provide common tasks to the developer in an easy and stable way. But, the wrapping code is the code that we want to unit test...

So for example, a Polyline Wrapper. I would need: - Acad Polyline class - Polyline Adapter Class, mimicking the Acad Polyline - Polyline Wrapper Class, providing stable and encapsulated code for common functionalities.

In (pseudo) code:

public class PolylineAdapter:IPolyline
{
    private Acad.Polyline acadPolyline; // initialized through constructor
    public void AddVertexAt(int i, IPoint2d pt) { // call acadPolyline.AddVertexAt }
}

public class PolylineWrapper
{
    private PolylineAdapter internalPolyline;

    public void AddVertex(WrappedPoint2d pt)
    {

        // this I can now unit-test

        writeEnableInternalPolyline();

        internalPolyline.AddVertexAt(0, pt.InternalPoint);

        writeDisableInternalPolyline();
    }
}
A: 

I don't really understand how the Adapter Pattern will fix your problem, but then again I'm no expert on that pattern.

I would fix this problem by writing a wrapper class around the API. Extract an interface from that wrapper and let your code work with the interface. When unit testing replace the 'real' interface implementation by a mock implementation of a wrapper.

Gerrie Schenck
Yes, that is kind of what I meant. The Adapter pattern seemed to describe that pretty well. I will add a code sample of what I have in mind
Bertvan
AFAIK an Adapter works by inheriting from a base class instead of implementing a common interface. I would recommend using an interface though, it will make it easier if you want to shift to dependency injection some day.
Gerrie Schenck
A: 

If you are writing your code for the autcad API and it is only for this you shouldn't need the adaptor pattern. The adaptor pattern is generally for fitting an existing object with one external interface to another, where they have generally the same methods but without the same argument names/types. If you are writing for an existing API you don't need to do this.

For the unit tests you probably need some "mock" objects to pretend to be the autocad API but without having any of the internal functionality (otherwise you will be testing your code and autocad). I should imagine that the autocad api is fairly well documented so writing some code to pretend to be it should be fairly easy.

Jeremy French
Could you provide a sample of how I could mock their API (I am familiar with Rhino Mocks)? Let's say I have a class that adds a Point to a Polyline, how would I unit-test that class? They don't provide Interfaces, only a class Acad.Polyline
Bertvan
I am afraid I don't know enough about the domain to give you an example
Jeremy French