Как получить доступ к приватному методу из сервиса Spring? - PullRequest
0 голосов
/ 18 марта 2019

У меня есть служба с открытыми методами для манипулирования базой данных, помеченная аннотацией org.springframework.transaction.annotation.Transactional.

Я хочу получить доступ к закрытому методу (без аннотации транзакций) через отражение Java: service.getClass().getDeclaredMethod('privateMethod', args).

Когда я звоню, я получаю java.lang.NoSuchMethodException.Когда я удаляю все аннотированные методы @Transactional, это работает.Есть ли причина для такого поведения и как я могу это решить?

public class MyService {

    @Transactional(readOnly = true)
    public Integer publicMethodMarkedWithTransactional(int a, int b) {
        //couple of database requests
        return privateMethod(b, a);
    }

    private Integer privateMethod(int a, int b) {
        return a + b;
    }

}

public class MyServiceTest {

    @Autowired
    private MyService service;

    @Test
    public void test() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method privateMethod = service.getClass().getDeclaredMethod("privateMethod", int.class, int.class);
        privateMethod.setAccessible(true);
        int res = (int) privateMethod.invoke(service, 5, 10);
        assertEquals(5 + 10, res);
    }

}

Ответы [ 2 ]

3 голосов
/ 18 марта 2019

Вы можете импортировать ReflectionUtils:

import org.springframework.data.util.ReflectionUtils;

И тест будет выглядеть примерно так:

@Test
public void test() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
   Method privateMethod = ReflectionUtils.findRequiredMethod(MyService.class, "privateMethod", int.class, int.class);
    int res = (int) privateMethod.invoke(service, 5, 10);
    assertEquals(5 + 10, res);
}

Однако я бы рекомендовал не писать тесты таким способом - вы должны найти способ протестировать свой API. Частные методы не являются частью API, и такое тестирование делает ваши тесты гораздо более хрупкими.

2 голосов
/ 18 марта 2019

Да, есть причина: обработка транзакций основана на прокси. Вы пытаетесь вызвать приватный метод на транзакционном прокси.

Прокси-сервер реализует только открытые методы службы, потому что вы не должны использовать отражение и вызывать закрытые методы. Они являются частными по причине.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...