переопределение метода в универсальном классе - PullRequest
0 голосов
/ 29 сентября 2011

Я рефакторинг некоторых юнит-тестов.По сути, я обнаружил, что модульные тесты различных клиентов реализуют набор методов, таких как: createClientWithNullResponse, createClientWithSuccessResponse и т. Д.

Мне было интересно, возможно ли в Java реализовать универсальное решение для этого, поскольку эти методыповторяются снова и снова в сотнях классов модулей, изменяя только сигнатуру метода.

Но тут есть хитрость.См. Пример метода:

/**
 * configures the client to return a succesful response
 * @return a client configured to return a succesful response
 */
private Client1 configureClientWithSuccesfulResponse()
{
    client = new Client1()
    {
        public CommonClientResponse processRequest( CommonsClientRequest commonsClientRequest )
        {
            CommonClientResponse commonClientResponse = new CommonClientResponse();
            commonClientResponse.setResponse( new Client1Response() );
            return commonClientResponse;
        }
    };
    return client;
}

Итак, client2 будет иметь тот же метод, за исключением того, что сигнатура имеет Client2, а переопределенный метод создает новый Client2Response, и то же самое с десятками клиентов.

Дополнительная информация: processRequest переопределяется, чтобы действовать как макет, устанавливая желаемый ответ для каждого метода.Client1 расширяет CommonsWS, который расширяет AbstractCommons, который является абстрактным классом, но содержит реализацию метода processRequest.

В общем, моя идея - создать базовый класс для всех модульных тестов с помощью набора универсальных методов.где я могу передать тип класса, а затем переписать processRequest для каждого.Я пытался:

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;
                };
            };
        }
    }

}

, но он даже не компилируется.Есть ли у вас какие-либо идеи о том, как я могу начать реализовывать это?

Ответы [ 2 ]

1 голос
/ 29 сентября 2011

Поскольку вы фактически пытаетесь создать анонимный класс, тип которого неизвестен во время выполнения, задумывались ли вы о вызове компилятора во время выполнения?Я сам этим не пользовался, но, возможно, стоит исследовать.Вы можете вызвать его, используя

JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler();

Обратите внимание, что это будет работать только в том случае, если приложение запущено в системе, в которой установлен JDK, как JRE (не включает javac) .

1 голос
/ 29 сентября 2011

Это сложный вопрос. Я предлагаю создать класс Factory, который будет возвращать каждый тип клиента, а вы предоставите ответ и передадите его фабрике. Что-то вроде:

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

И вы называете это с помощью:

    factory.createClient1(new Client1Response());

Есть еще некоторое дублирование, но это помогает. Немного. Что ты думаешь?

...