overriding a method in a generic class
Im refactoring some unit tests. Basically, i ve found that unit tests of different clients implement a bundle of methods such as: createClientWithNullResponse, createClientWithSuccessResponse, etc.
I was wondering if its possible in Java to implement a generic solution to this, since this methods are repeated over and over in hundreds of unit classes, changing only the method signature.
But, there is a tricky. See a method example:
/**
* configures the client to return a succesful response
* @return a client configured to return a succesful response
*/
private Client1 configureCl开发者_C百科ientWithSuccesfulResponse()
{
client = new Client1()
{
public CommonClientResponse processRequest( CommonsClientRequest commonsClientRequest )
{
CommonClientResponse commonClientResponse = new CommonClientResponse();
commonClientResponse.setResponse( new Client1Response() );
return commonClientResponse;
}
};
return client;
}
So, client2 will have the very same method except that signature have Client2, and the overrided method creates a new Client2Response, and the same with dozens of clients.
Additional information: processRequest is overrided to act as a mock, setting the response i wish for each method. Client1 extends CommonsWS that extends of AbstractCommons, which is an abstract class but contains the implementation of processRequest method.
All in all, my idea is to create a Base class for all unit tests, with a bundle of generic methods where i can pass the class type, and then rewrite the processRequest for each one. Ive tried :
public class base <T extends AbstractCommonClient>{
private T configureClientWithNullResponse(Class <? extends AbstractCommonClient> clazz, Class< ? extends ClientResponse> clazz1)
{
try
{
return clazz.newInstance()
{
CommonClientResponse processRequest( CommonsClientRequest commonsClientRequest )
{
CommonClientResponse commonClientResponse = new CommonClientResponse();
commonClientResponse.setResponse( clazz1.newInstance() );
return commonClientResponse;
};
};
}
}
}
but it not even compile. Do you have any ideas of how i can begin implementing this?
As you are effectively trying to create an anonymous class whose type is unknown at runtime, have you considered invoking the compiler at runtime? I haven't used it much myself, but it may be worth investigating. You can invoke it by using
JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler();
Note that this will only work if the application is run on a system where JDK is install, as JRE (does not include javac
).
This is a tricky question. I suggest create a Factory class that would return each type of client, and you provide the response and pass it to the factory. Something like:
public class ClientFactory {
public static createResponse(ClientResponse response) {
CommonClientResponse commonClientResponse = new CommonClientResponse();
commonClientResponse.setResponse(response);
return commonClientResponse;
}
public static Client1 createClient1(final ClientResponse response) {
return new Client1() {
public CommonClientResponse processRequest(CommonsClientRequest unused) {
return createResponse(response)
};
}
};
public static Client2 createClient2(final ClientResponse response) {
return new Client2() {
public CommonClientResponse processRequest(CommonsClientRequest unused) {
return createResponse(response)
};
}
};
..... // same for every type of Client
And you call it using:
factory.createClient1(new Client1Response());
There is still some duplication, but it helps. A little. What do you think?
精彩评论