Как имитировать нестатический логгер с помощью PowerMock?

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

class Service {
    private final Logger lgr = LoggerFactory.getLogger(Service.class);

    public void doService() {
        lgr.info("Do Service");
    }
}

public class Controller {
    private final Logger lgr = LoggerFactory.getLogger(Controller.class);

    @Autowired
    private Service service;

    protected void doSomething() {
        //do something
        lgr.info("LOG something"); // lgr line
        // do something else

    }
}

И соответствующий тестовый класс, который выглядит так:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ControllerTest.class, LoggerFactory.class})
public class ControllerTest {
    private Controller controller;

    @Mock
    private Service service;

    @Before
    public void init() {
        controller = Mockito.mock(Controller.class, Mockito.CALLS_REAL_METHODS);
    }

    @Test
    public void testDoSomething() {
        controller.doSomething();  // calling doSomething method of Controller class
        // some other statements
    }
}

Здесь, когда вызов переходит к методу doSomething (), в строке lgr line объект lgr имеет значение null, из-за чего мой модульный тест завершается с ошибкой с исключением NullPointerException.

Может кто-нибудь, помогите мне это исправить?


person user97    schedule 14.04.2020    source источник
comment
Сделайте его статическим и сделайте следующее: stackoverflow.com/questions/8948916/   -  person Tom Cools    schedule 14.04.2020
comment
Я знаю, что после создания статического регистратора я могу использовать mockstatic и т. Д., Но в существующем классе уже есть класс статического регистратора, поэтому я предпочитаю не изменять его.   -  person user97    schedule 14.04.2020
comment
Хорошо, но тогда почему вы пытаетесь добавить еще один регистратор? Мне это кажется немного странным.   -  person Tom Cools    schedule 14.04.2020
comment
Я не пытаюсь добавить какой-либо регистратор, есть существующий класс, который имеет нестатический регистратор, и нестатический метод, который регистрирует что-то с этим объектом регистратора. Я пытаюсь написать UT, чтобы проверить что-то в этом методе, но это дает NPE, поскольку объект lgr в этом методе имеет значение null.   -  person user97    schedule 14.04.2020
comment
Вы пытаетесь проверить, вызывается ли регистратор? Или вы тестируете controller.doSomething ()? если последнее, не имитируйте его, а создайте новый экземпляр: @Before public void init () {controller = new Controller ()}   -  person Tom Cools    schedule 14.04.2020
comment
Я издеваюсь над этим, так как в классе Controller есть много полей с автоматическим подключением, которые, как мне казалось, было бы сложно внедрить без добавления полей @Mock.   -  person user97    schedule 14.04.2020
comment
Вы никогда не издеваетесь над классом, который тестируете, вы только издеваетесь над зависимостями. :-) На вопросы в будущем: пожалуйста, поделитесь всем классом (вы поделились только частью, что затрудняет понимание того, что вы хотите сделать). Если вы обновите этот вопрос своим полным классом, я посмотрю на него.   -  person Tom Cools    schedule 14.04.2020
comment
Спасибо за добавление. Для того, что вы хотите делать, вам на самом деле не нужен PowerMock :-). Вот что вам следует изменить: - Не ставьте autowired на поле. Создайте конструктор, в который вы передаете Service и (необязательно) помещаете Autowired в конструктор. - в вашем тесте Before создайте новый контроллер и передайте Mocked Service в конструктор. Перед общедоступным void init () {controller = new Controller (service); }   -  person Tom Cools    schedule 14.04.2020
comment
Спасибо, но есть ли способ программно ввести фиктивный объект Service в фиктивный объект Controller?   -  person user97    schedule 14.04.2020
comment
Через конструктор или с помощью MockitoAnnoations.initMocks () (см. stackoverflow.com/questions/32263208/)   -  person Tom Cools    schedule 14.04.2020