I'm considering rewriting a C#/.NET AutoCAD plugin that currently has no unit or integration tests. AutoCAD objects only exist inside the AutoCAD runtime, so testing code that directly manipulates polylines and other API types would require integration tests or a substantial abstraction layer.
I started extracting domain logic into separate classes. For example, a Zone represents an AutoCAD polyline and uses interfaces such as IZoneDataProvider and IZoneGeometry. The production implementation would wrap AutoCAD objects, while tests could use in-memory implementations. This works reasonably well for things like assigning a ZoneId or checking whether a point lies inside the zone.
However, the abstractions become more complicated as the business rules grow. For example, when a zone is created, its polyline color and the colors of related objects need to change based on the ZoneId. Adding that behavior means introducing another interface, such as IZoneColorEntity, and making the AutoCAD adapter implement several interfaces that closely mirror the AutoCAD API.
At that point, it feels like I'm creating abstractions mainly to make unit testing possible, even though the business logic is inherently tied to manipulating CAD objects. Would it be better to skip a separate domain layer and focus on integration or functional tests using real AutoCAD scenarios? Or is extracting the logic and building these interfaces still worthwhile?
2 Answers
Unit tests can be useful, but not every piece of code needs to be forced into a mock-friendly design. The important distinction is whether you have substantial logic that can run independently of AutoCAD. Geometry calculations, rules for assigning IDs or colors, and decisions about which objects should change can be tested with simple values or small domain types. The actual translation to AutoCAD properties should be covered by integration tests.
If the domain layer mostly forwards calls to AutoCAD, adding interfaces for every property may just duplicate the external API and create another contract to maintain. In that case, focused integration tests with realistic AutoCAD documents may provide more confidence than a large suite of mocks.
I’ve found that tests using real scenarios and real integrations can be less fragile than heavily mocked unit tests. A mock can match the interface while the actual AutoCAD behavior, object lifecycle, transactions, or property restrictions have changed, so the unit tests may still pass while the plugin fails in practice.
You don’t have to choose between a giant domain project and no tests at all. Extract only logic that is genuinely independent and valuable to test in isolation, then use integration or functional tests for the parts that exist specifically to coordinate with AutoCAD. If most of the plugin is orchestration and the rules are simple, prioritizing a smaller number of end-to-end scenarios is a reasonable design choice.

The color example is a good warning sign. If the abstraction only renames AutoCAD properties and passes values through, it may not be buying you much. I’d keep genuinely complex rules separate, but test the adapter and AutoCAD behavior together.