简体   繁体   中英

Java - Testing code that relies extensively on an external service API

I'm working on a project that ties into an API that makes calls to an external service. Things are going well enough, but we need to start some serious testing. The fun part? The vast majority of calls to this service go through a single, enormous class (We'll call this Mastadon.class. It seems fitting.) within the API. There are a massive number of methods in Mastadon for making all kinds of different calls and our project uses a good number of them. A number of them are just public convenience methods that bounce things to private ones, but the number is still quite large.

So now the fun of testing comes. We'd certainly like to avoid making constant calls out to this service. Some testing will even require certain actions to be taken on the other end and certain actions/results sent back from the service, which we'd have to do manually or do some fancy automation work on the other end, which we'd rather not do.

We could make a mock child class for the Mastadon class, but that's a lot of methods to stub out, and we may well need varying behavior depending on the test and input. That's a lot of muckery. We could use a mock framework (we currently use JMockit for some things), but again, that's a LOT of mockery of the service and mocking can be a real pain in the neck. I've also considered doing a bit of retooling to make an injectable proxy class (may not be the precise phrase I'm looking for here, but you get the idea) that acts as a go-between for our code and the Mastadon class. Our code will never actually touch Mastadon, instead using MastadonProxy or whatever we call it to pass calls through. This would mean some retooling of the project and further work, but might be easier in the long run as we could build a MastadonTestProxy and stub out only what's needed there, maybe even with some injectable behavior. It would be a lot less messy than a MastadonTest class with a bajillion methods that simply refer to the parent Mastadon method because we don't need to test that one in particular.

What say you? This API did not seem to be built with testing in mind. We do have the source code for the whole thing, but would prefer not to make any changes to it if it can be helped. I'm leaning toward the injectable proxy class, but maybe there's a better way of handling this, especially when it comes to end-to-end integration testing.

EDIT: I also realized that the proxy class may not work as there are a number of other objects with their own convenience methods in the API that wind up going through Mastadon as well. So ObjectA may have a doThis() method that winds up going through Mastadon's doThis() method behind the scenes. I'm thinking that the class extension/mock avenue may be the only way to go with this...

EDIT: Another problem. Mastadon inherits from a marginally smaller abstract class, which has another child class as well. I'll need to put up a facade for everything in all three of them, but that leaves me with the fun of sorting out how to properly facade all of these classes in a way that would actually work. In addition, I'll need to keep an instance of each handy (or a factory to create them when needed) to pass the calls along, and there would need to be some state, perhaps changes of variables within them, etc.

I'd recommend putting in some time for a proper testing framework by using a combination of the two approaches you say you're considering.

(1) Use a fake injectable resource to proxy to functionality in that class, and

(2) Use testing extensions to that class/wrapping interfaces to hide the functionality you don't need. This is where JMock is amazing -- at least half the things it can help you with will come as really nice surprises.

While at first this might seem like an awful lot of work, it's the best way of building a flexible and extensible automated/regression testing framework. Which sounds like what you are/should be going for, unless you intend to redo the same work for every future project you build atop your "Mastodon.class".

If you're going for something big, best to put in some effort. Remember what writing code is like ...: one mistake and you have to support it the rest of your life.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM