Ложный доступ к внешнему объекту из локального внутреннего класса - PullRequest
3 голосов
/ 11 апреля 2019

У меня есть класс с локальным внутренним классом в одном из его методов:

public class Outer {
    String hello = "hello";

    public void myMethod() {

        class Inner {
            public void myInnerMethod() {
                System.out.println(hello);         
            }
        }

        [...really slow routine...]

        (new Inner()).myInnerMethod();
    }
}

Я бы хотел проверить myInnerMethod(). Поэтому я создаю экземпляр локального внутреннего класса с помощью отражения и вызываю myInnerMethod() для него.

public void test() {
    Object inner = Class.forName("Outer$Inner").newInstance();
    inner.getClass().getDeclaredMethod("myInnerMethod").invoke(inner); // hello will be null
}

Но когда myInnerMethod() получает доступ к hello, который находится в области действия класса Outer, это null.

Есть ли способ издеваться или иным образом передать привет myInnerMethod()?

Я знаю, что мог бы реорганизовать свой код, извлекая внутренний класс или просто проверяя открытые методы Outer. Но есть ли еще способ сделать это?

1 Ответ

1 голос
/ 11 апреля 2019

Вам потребуется выполнить небольшой рефакторинг, прежде чем можно будет проверить внутреннее поведение:

1) Создать метод уровня пакета, который будет содержать код, вызываемый из myInnerMEthod:

public class Outer {
    String hello = "hello";

    public void myMethod() {

        class Inner {
            public void myInnerMethod() {
                Outer.this.printHello(hello);    // !!! change here     
            }
        }

        [...really slow routine...]

        (new Inner()).myInnerMethod();
    }

    void printHello(String hello){/* */}   // !! add this
}

2) Следите за классом Outer и убедитесь, что printHello вызван с переменной экземпляра hello:

public void test() {
    // Arrange
    Outer outerSpy = spy(new Outer());
    doNothing().when(outerSpy).printHello(anyString()); // optional

    // Act
    outer.myMethod();

    // Assert
    verify(outerSpy).printHello("hello");
}
...