Не нарушайте мою приватность

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Добрый день! Статья будет про один совершенно незначительный момент в кодировании.
Например, многие мои коллеги сказали - Doch, das ist ganz normal! "А, чё, все норм, нашел к чему придраться!" Но, тем не менее.

Есть несколько вещей в написании кода которые меня бесят. Ну, на самом деле не несколько. :), чем старше становлюсь, тем больше и больше таких вещей, характер не лучшает. Но в топе - когда девелоперы пишут тесты к private методам. А, нет! Когда они ради этого убирают слово private у метода и метод становится package-private.

Вот, ты такой ревьювишь класс, строк этак на 3К, написанный в лучших традициях процедурного программирования, а там 10 методов public, 10 private, а еще 15 package-private. И про интерфейсы мы не слышали - это ж сервис, давай так прям так и инжектить! Ок, думаешь ты, сейчас рукава засучим, вынесем все public методы в интерфейс, helper-ы, их в отдельный package - короче распилим это безумство на части согласно SRP. Но тут же обнаруживаешь, что package-private методы давно дергаются из других мест. Дык у нас все классы в один package свалены! If something can be misused, it will be misused for sure, как говорится.

Да-да, все знают, писать тесты к private методам не надо, если ты это делаешь, то что-то не так с дизайном, и так далее. Но, блин, люди все равно это делают, и надо сказать, не без причин. Представте, что упомянутый выше класс вообще был с zero test coverage. А рефакторить надо. Вот так и появляются package-private методы. Но как же нам быть - вон и Whitebox из Mockito выпилили, конечно в PowerMock он остался, но ради этого тащить PowerMock в проект, да и синтаксис не лучше прямого вызова через reflection. Можно конечно свой велосипед написать, но... И так и так не айс получается.

А вот представьте, что для доступа к private элементам класса - методам, полям, у нас есть интерфейс. Что за фигня, вы скажете, совсем парень заработался. А вот так:

Есть класс:

public class ObjectWithPrivates {
    private final AtomicInteger count = new AtomicInteger(0);
    private String name;

    private String methodToTest(String in) {
        return name + in + count.incrementAndGet();
    }
}

Тест:

interface TestPrivates {
    void setName(String name);
    String methodToTest(String in);
    AtomicInteger getCount();
}

@Test
void testPrivates() {
    ObjectWithPrivates obj = new ObjectWithPrivates();
    TestPrivates objWithPrivates = API.lookupPrivatesIn(obj)
                                      .usingInterface(TestPrivates.class);

    objWithPrivates.setName("Andromeda");
    String in = objWithPrivates.methodToTest("in");
    AtomicInteger count = objWithPrivates.getCount();

    Assertions.assertEquals("Andromedain1", in);
    Assertions.assertEquals(1, count.get());
}

Как видите, с помощью интерфейса мы можем дергать private методы, и получать доступ к private полям. Ну и по коду сразу можно сказать, что происходит. Имейте ввиду, что все манипуляции происходят с obj и можно, например, засетить все private поля у obj и потом дернуть public метод.

Можно получить доступ к private полям/методам родительского класса:

TestPrivates accessToPrivates = API.lookupPrivatesIn(obj)
                                   .lookupInSuperclass()
                                   .usingInterface(TestPrivates.class);

А можно и статические методы дергать:

TestPrivates accessToPrivates = lookupPrivatesIn(SomePOJOClass.class)
                                .usingInterface(TestPrivates.class);
accessToPrivate.someStaticPrivateMethod();

А можно и объект создать через private конструктор.

Под капотом там стандартный reflection и Dynamic Proxy, никаких дополнительных зависимостей.

Вот ссылка на проект testprivates. Использовать только для тестов.

Всех с наступающим, не болейте!

Источник: https://habr.com/ru/post/535426/


Интересные статьи

Интересные статьи

Кто бы что ни говорил, но я считаю, что изобретение велосипедов — штука полезная. Использование готовых библиотек и фреймворков, конечно, хорошо, но порой стоит их отложить и создать ...
Предыстория Когда-то у меня возникла необходимость проверять наличие неотправленных сообщений в «1С-Битрикс: Управление сайтом» (далее Битрикс) и получать уведомления об этом. Пробле...
Битрикс24 — популярная в малом бизнесе CRM c большими возможностями даже на бесплатном тарифе. Благодаря API Битрикс24 (даже в облачной редакции) можно легко интегрировать с другими системами.
Компании растут и меняются. Если для небольшого бизнеса легко прогнозировать последствия любых изменений, то у крупного для такого предвидения — необходимо изучение деталей.
На сегодняшний день у сервиса «Битрикс24» нет сотен гигабит трафика, нет огромного парка серверов (хотя и существующих, конечно, немало). Но для многих клиентов он является основным инструментом ...