Assuming you're not looking for a mocking framework, because they're ultra-ubiquitous and easy to find, there are a few things worth noting up front:
- There is "never" anything you should "always" do.
It's not always best to wrap up a third party library. If your application is intrinsically dependent on a library, or if it's literally built around one or two core libraries, don't waste your time wrapping it up. If the libraries change, your application will need to change anyway.
- It is OK to use integration tests.
This is especially true around boundaries that are stable, intrinsic to your application, or cannot be easily mocked. If those conditions are met, wrapping and mocking will be complicated and tedious. In that case, I'd avoid both: don't wrap and don't mock; just write integration tests. (If automated testing is a goal.)
- Tools and framework cannot eliminate logical complexity.
In principle, a tool can only cut down on boilerplate. But, there's no automate-able algorithm for taking a complex interface and making it simple -- let alone taking interface X and adapting it to suit your needs. (Only you know that algorithm!) So, while there are undoubtedly tools that can generate thin wrappers, I'd suggest that they're not already ubiquitous because, in the end, you still need to just code intelligently, and therefore manually, against the interface even if it's hidden behind a wrapper.
That said, there are tactics you can use in many languages to avoid referring directly to a class. And in some cases, you can "feign" an interface or thin wrapper that doesn't actually exist. In C#, for example, I would go one of two routes:
- Use a factory and implicit typing.
You can avoid the effort of fully wrapping a complex class with this little combo:
// "factory"
class PdfDocumentFactory {
public static ExternalPDFLibraryDocument Build() {
return new ExternalPDFLibraryDocument();
}
}
// code that uses the factory.
class CoreBusinessEntity {
public void DoImportantThings() {
var doc = PdfDocumentFactory.Build();
// ... i have no idea what your lib does, so, I'm making stuff but.
// but, you can do whatever you want here without explicitly
// referring to the library's actual types.
doc.addHeader("Wee");
doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
return doc.exportBinaryStreamOrSomething();
}
}
If you can avoid storing these objects as members, either through a more "functional" approach or by storing them in a dictionary (or whatever), this approach has the benefit of compile-time type checking without your core business entities needing to know exactly what class they're working with.
All that is required is that, at compile time, the class returned by your factory actually has the methods on it that your business object is using.
- Use dynamic typing.
This is in the same vein as using implicit typing, but involves another tradeoff: You lose compile-type checks and gain the ability to anonymously add external dependencies as class members and inject your dependencies.
class CoreBusinessEntity {
dynamic Doc;
public void InjectDoc(dynamic Doc) {
Doc = doc;
}
public void DoImortantThings() {
Doc.addHeader("Wee");
Doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
return Doc.exportBinaryStreamOrSomething();
}
}
With both of these tactics, when it comes time to mock ExternalPDFLibraryDocument
, as I stated earlier, you have some work to do -- but, it's work you'd need to do anyway. And, with this construction, you've avoided tediously defining 100's of thin little wrapper classes. You've simply used the library without looking directly at it -- for the most part.
With all of that said, there are three big reasons I would still consider explicitly wrapping up a third party library -- none of which would hint at using a tool or framework:
- The specific library is not intrinsic to the application.
- It would be very expensive to swap without wrapping it up.
- I don't like the API itself.
If I don't have some level concern in all three of those areas, you don't make any significant effort to wrap it up. And, if you have some concern in all three areas, an auto-generated thin wrapper isn't really going to help.
If you've decided to wrap a library up, the most efficient and effective use of your time is to build your application against the interface you want; not against an existing API.
Put another way, heed the classical advice: Postpone every decision you can. Build the "core" of your application first. Code against interfaces that will eventually do what you want, which will eventually be fulfilled by "peripheral stuff" that doesn't exist yet. Bridge the gaps as-needed.
This effort may not feel like time-saved; but if you feel you need a wrapper, this is the most efficient way to do it safely.
Think of it this way.
You need to code against this library in some dark corner of your code -- even if it's wrapped up. If you mock the library during testing, there's unavoidable manual effort there -- even if it's wrapped up. But, that doesn't mean you need to directly acknowledge that library by name throughout the bulk of your application.
TLDR
If the library is worth wrapping, use tactics to avoid widespread, direct references to your 3rd party library, but don't take shortcuts to generate thin wrappers. Build your business logic first, be deliberate about your interfaces, and emerge your adapters organically, as needed.
And, if it comes to it, don't be afraid of integration tests. They're a little fuzzier, but they still offer evidence of working code, and they can still easily be made to keep regressions at bay.
Best Answer
You may transfer existing (already processed files in previous runs) output files into the output folder just to simulate the work of the third party API in the unit test code. This will suffice if you are unit testing your own functionality and not the third party functionality.