We are developing applications for use within AutoCAD. Basically we create a Class Library Project, and load the .dll in AutoCAD with a command (NETLOAD).
As so, we can use commands, "palettes", user controls, forms etc...
AutoDesk provides an API through some dll's, running in their program directory. When referencing these dll's you can only call the dll's at runtime while loading your app in AutoCAD (This is a licensing security from AutoDesk).
For us, while developing, this is not a problem, we need to visually test within the context of AutoCAD, so we just set the Debug Properties so that they start acad.exe and load our dll with a script in the acad.exe parameters.
The problem is, when trying to unit test our code, NUnit or mstest are not running from within the AutoCAD context and they also cannot start it. There exist a tool called Gallio, which has provided an interface with AutoCAD, so that it can run Unit test through IPC with Named Pipes.
However, this solution is, for me, too much of a hassle. I want to be able to quickly write tests without having to leave my beloved IDE.
So, what, from a "good design view" would be a good approach to this problem? I'm thinking I would basically need a testable codebase which is not referencing the AutoCAD dll's and a non-testable that does references the untestable AutoCAD dll's.
I'm sure there are ways to get this to work: ( IOC, DI, Adapter Pattern,. .) I just don't these principles in depth and thus I don't know which route will best suit my purposes and goals.
The first step is to triage your code for parts which need AutoCAD and parts which are really independent. Create unit tests for the independent parts as you usually would.
For the other parts, you need mockups which behave like AutoCAD. Make them as simple as possible (for example, just return the correct answers in the methods without doing any calculations). Now, you need several sets of classes:
A set of interfaces which your code uses to achieve something (for example, load a drawing).
A set of implementations for said set of interfaces which call the AutoCAD dlls.
A set of classes which try the implementations within the context of AutoCAD. Just create a small UI with a couple of buttons where you can run this code. It is used to reassure yourself that your mockups do the right thing. Log method parameters and results to some file so you can try how AutoCAD responds. If a mockup breaks, you can use this code to verify what AutoCAD is doing and you can use it as a reference when developing the mockups.
When you know how AutoCAD responds, create the mockups. In your tests, create them with the desired results (and errors, so you can test error handling, too). So when you have
boolean loadDrawing(File filename), create a mockup which returns
true for the filename
false for anything else.
Use a factory or DI to tell your application code which implementation to use. I tend to have a big global config class with a lot of public fields where I simply store the objects to use. I can set this up in the beginning, it's fast, it's easy to understand. If you need to create objects at runtime, then put factories in the config class which generate the objects for you, so you can swap them out.