Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Untestable Braintree API: Should I alter the source code or individually wrap every class? [duplicate]

I am working with the Braintree API for .NET to take care of processing payments. Their business does a fine job of processing payments and the API wrapper works for straightforward use. However, the provided API wrapper begins to fail quickly upon closer investigation or more strenuous use; for example, it contains hand-rolled enums. My problem comes with unit testing my code that uses this wrapper.

In order to do this, I essentially need to mock up my own 'fake' Braintree gateway that will have some known values in it, generate errors when requested, etc. My plan of attack was to override the functionality of the Braintree API wrapper and reroute the requests to a local in-memory endpoint. Then I could use dependency injection to link up the proper gateway/wrapper at runtime.

Initially, it seemed to be going swimmingly: despite the sins against software engineering that had been committed in the API wrapper, every method that I would need to override was miraculously marked virtual. However, that came to a screeching halt: almost constructor in the API wrapper is marked internal. As such, I can neither inherit off of these classes nor create them at whim to store for testing.

An aside: I grok internal constructors, and the reasons that one would legitimately want to use them. However, I have looked at the source code for this, and every internal constructor performs only trivial property assignments. As such, I am comfortable in claiming that a different coding practice should have been followed.

So, I'm essentially left with three options:

  1. Write my own API wrapper from scratch. This is obviously doable, and holds the advantage that it would yield a well-engineered infrastructure. The disadvantages, however, are too numerous to list briefly.

  2. Pull the source code from the API down and include it in my solution. I could change all of the internal constructors to be whatever I need to make them work. The disadvantage is that I would have to re-update all of these changes upon every subsequent API wrapper release.

  3. Write wrapper classes for every single object that I need to use in the whole API wrapper. This holds the advantage of not altering the provided source code; the disadvantages are large, though: essentially rewriting every class in the wrapper three times (an interface, a Braintree API wrapper adapter, and a testable version).

Unfortunately, all of those suck. I feel like option 2 may be the least bad of the options, but it makes me feel dirty. Has anyone solved this problem already/written a better, more testable wrapper? If not, have I missed a possible course of action? If not, which of those three options seems least distasteful?

like image 396
eouw0o83hf Avatar asked Nov 04 '22 06:11

eouw0o83hf


2 Answers

Perhaps this stackoverflow entry could help

Also, A random blog entry on the subject

like image 107
radarbob Avatar answered Nov 10 '22 07:11

radarbob


Since you're not testing their API, I would use a Facade pattern. You don't need to wrap everything they provide, just encapsulate the functionality that you're using. This also gives you an advantage: If you decide to ditch that API in the future, you just need to reimplement your wrapper.

like image 44
Daniel Mann Avatar answered Nov 10 '22 06:11

Daniel Mann