0

I have some automated RESTful API tests in Java. They use a proprietary Java library (restLibOne) to make API calls. The proprietary library is similar in concept to REST Assured, but vastly different from it in terms of how it makes API calls. Now, there is another proprietary library, restLibTwo, that will replace restLibOne and is vastly different from it. Who knows, in the future there may be yet another replacement.

I need to convert the code to use restLibTwo instead of restLibOne. I am not sure how to approach this project but I have an idea. I want to start by making some "generic" class that represents how REST API calls are made. Then, the functions in this class will use any library to make those calls. For example:

class GenericApiCaller {

public static MyResponseObject doGet(MyRequestObject request){
  // 1 - use any library to make api call by using the data in request object.
  // 2 - cast result of 1st step into MyResponseObject response.
  // 3 - return response.
}

public static MyResponseObject doPost(MyRequestObject request){

}

// etc...
}

class MyRequestObject {
// It stores the information needed to make a request to any rest service - url, body, headers etc.
// Rest assured or whichever library you like can pick up those information from this object.
}

The problem is that I don't know how to design functions to make API calls. I don't know what inputs are needed to make API calls besides simple inputs like URL, headers, method, body, etc., so I don't know what arguments my API call making functions should have.

Then, I don't know what all things a response must have besides the simple ones like code, headers, body, etc., so, I don't know what kind of object should be returned by my API call making functions.

Is there already a generic class/code that does what I want? If not, then how should I go about designing my own class? Is this project best given to someone who is an expert in API automation?

  • 2
    My $.02...I think that the developers should be the one unit-testing their API's; not you. I have done this in the past and it was really annoying; especially when they made a change to their API and forgot to inform you of it. – Brian Feb 27 at 16:25
3
+25

I generally agree with @alexey-r... You should probably just re-write the code when the library changes.

Companies change libraries for a reason; new features, better features, streamlined configuration, etc. If you try to abstract too much you are:

  1. Building your own API to connect with someone else's API
  2. Making it difficult to take advantage of the library improvements

If you do insist on this abstraction, then I would recommend creating a custom object that gets passed to each of your methods, then update the object with the results. There are only a set number of things transmitted; headers/cookies sent, the body sent, the endpoint, the headers received, and the content received. The difficulty is in making your object powerful enough to handle all the variations:

  1. Is the body null, JSON, or XML?
  2. Is the content returned null, JSON, XML?
  3. How to handle all the return codes?
  4. Do you need to made an auth call first to get some sort of validation token?
  5. How do you pass around the validation token?

By the time you're done, you've built your own joeRestLib that will need to be updated as often as the library you're supposed to be connecting to. Your time would likely be better spend making better tests and eking out all the power of using restLibTwo directly.

  • Thanks. Can we do 4 & 5 in different ways ? If yes, then what are some of the ways ? – MasterJoe2 May 8 at 4:27
4

I would approach with just refactoring the code to use restLibTwo. Here are few points on why I would do that:

  1. Rest calls are just HTTP calls. Moving to another lib (for example RestAssured) would be likely motivated by surrounding functionality (like using gherkin notation or integrated json/xml parsing). So usually nobody tests REST with the lib that just allow to call HTTP endpoints. Hence you wouldn't be able to effectively wrap it with some generic model since the "surrounding" functionality would be different for different libs, will use different classes, etc.

  2. Despite HTTP protocol is quite simple one, it would still require some level of awareness on how the things are done. You can take a look at this specification to get aware of what methods should be supported, what can be used when you send data and what can be returned from the server. You will have to consider all those things, however it is not necessary that you will ever use even 30% of all HTTP features in your tests.

  3. Basically what you want to do is to re-invent the wheel by introducing some sort of restLibThree. When "they" will take decision to move to new rest lib, you will probably have to reconsider your model taking into account what I mentioned in p.1

  • Hi Alexey. Thanks for your answer. I just updated my pseudocode to clarify what I was trying to do. – MasterJoe2 Mar 13 at 17:39
3

You can take a look at Google HTTP Client Library for Java, that offers:

Pluggable HTTP transport abstraction that allows you to use any low-level library such as java.net.HttpURLConnection, Apache HTTP Client, or URL Fetch on Google App Engine.

You would need to write your own binding between Google HTTP Client API and restLibTwo. Note, however, there might be additional trade-offs:

  • although all HTTP/REST clients are based on well-defined and stable standards (HTTP, TCP, REST), they may have features that are missing in Google HTTP Client, so they might not be exposed

I would carefully think what are the reasons that restLibTwo was chosen over restLibOne, what are the differences between them and what are the common parts.

  • Thanks for your answer. I just updated my pseudocode to clarify what I was trying to do. – MasterJoe2 Mar 13 at 17:39
2

I believe Alexey and MivaScott have provided good advice here. I would like to add some additional thoughts on why coding to use any possible REST API client may not be the best idea.

Some of this will look blunt, but it is not a criticism of you.

I think what you're trying to code is an overcompensation for mistakes that people have made when designing your test framework. You see a lot of work ahead of you, and want to make sure that any future work to solve the same problem is limited.

I would suggest taking a step back and re-evaluating. Before undertaking the refactor, be sure that the library you're moving to is capable of doing what you need it to, both now and in the foreseeable future. Is it a mature library? How many years has it been around? How many other libraries is it included in? Is it active? Are there lots of open bugs on its issue tracker?

Be confident that the library you're moving to is what your framework will use for years to come. Then when you're confident, just make the change to the new library.

Another factor here is creating an overly-complicated abstraction layer is likely to lead to more issues for your team in future. You're asking this question on SQA because you don't know how to do this, and your team don't know how to do this. The chances of your tests being thrown out and people starting them again from scratch is a lot higher when you start putting this level of complexity into it. If nobody understands what the framework is doing, it will not be maintainable.

If you really want to go ahead with your strategy, it may be worth asking this question on the main StackOverflow site instead. This is more of a programming question.

  • Thanks for your answer. I had asked the same question on SO long ago and it got 2 votes to close. No comments, no answers. I expected such a response and that is why I posted the question here also. I'll try to put a bounty in SO also and see if things improve - stackoverflow.com/questions/54900036/… – MasterJoe2 Mar 14 at 19:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.