Mockito не может вводить моки

Я использую Mockito и пытаюсь внедрить Mock CustomFileHandler в свой класс REjercicioDAO для целей тестирования. Дело в том, что мой тест не генерирует исключений, но он не внедряет мой фиктивный объект, оригинальный @Autowired CustomFileHandler не заменяется. Вот мой код:

@Repository
public class REjercicioDAO extends ARHibernateDAO < REjercicio > implements IREjercicioDAO {

    @Autowired
    public ICustomFileHandler customFileHandler;

    ...

}

И вот мой тест:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = ATest.CONTEXT_CONFIGURATION)
public class REjercicioDAOTest extends ATest {

    @Mock private ICustomFileHandler customFileHandler;

    @Autowired
    @InjectMocks
    private IREjercicioDAO rEjercicioDAO;

    @Before
    public void before () {

        MockitoAnnotations.initMocks(this);

        ...

    }

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

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

GhostCat 08.07.2019 20:40
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
4 754
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

The thing is, my test throws no exceptions, but it doesn't inject my mock object

Неудивительно. Этот способ внедрения макета остается тихим, даже если ни одна инъекция не увенчалась успехом. Из InjectMocks javadoc (выделено не мной!):

Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won't report failure; i.e. you will have to provide dependencies yourself.

Хотя Mockito не сообщает об ошибке, я очень не рекомендую использовать этот API.

Что касается вашей реальной проблемы, посмотрите на это:

@Autowired
@InjectMocks
private IREjercicioDAO rEjercicioDAO;

Вы аннотируете поле как аннотацией Spring, так и Mockito. Вас устраивает порядок их обработки? Они взяты из двух разных библиотек. Я не говорю, что это никогда не сработает (удача и случайность существуют), но вы действительно думаете, что это надежно?

Чтобы выполнить ваше требование, вы можете написать что-то подобное, что делает что-то в два явных шага:
- создание экземпляров объектов: имитация зависимости и внедрение пружинной зависимости
- набор отношений: между фиктивной зависимостью и пружинной зависимостью

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = ATest.CONTEXT_CONFIGURATION)
public class REjercicioDAOTest extends ATest {

    @Mock 
    private ICustomFileHandler customFileHandler;

    @Autowired        
    private IREjercicioDAO rEjercicioDAO;

    @Before
    public void before () {    
        MockitoAnnotations.initMocks(this);
        // Set explicitly the fileHandler dependency
        rEjercicioDAO.setFileHandler(customFileHandler);         
    }
 }

Спасибо, я думаю, что я просто буду использовать сеттер для зависимости, потому что это проще, чем иметь дело с конфигурацией и интеграцией библиотеки.

David Antelo 08.07.2019 20:54

Нет: спасибо вам за то, что вы изменили свой подход! Легче, а также действительно яснее!

davidxxx 08.07.2019 20:56

Вы пытаетесь смешать ИТ с модульным тестом.

1) Если вы используете Spring Boot:

@MockBean
private ICustomFileHandler customFileHandler;

@Autowired
private IREjercicioDAO rEjercicioDAO;

Вот и все..

2) Spring Boot не используется:

public class TestConfig{

    @Bean
    @Primary
    public ICustomFileHandler customFileHandler(){
       return Mockito.mock(ICustomFileHandler.class);
    }

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = ATest.CONTEXT_CONFIGURATION, classes=TestConfig.class)
public class REjercicioDAOTest extends ATest {

   @Autowired
   private ICustomFileHandler customFileHandlerMock; 

    @Autowired
    private IREjercicioDAO rEjercicioDAO;

Макет вводится, и вы можете настроить его в своем тесте по своему усмотрению.

Спасибо за ответ, но что вы имеете в виду, когда я смешиваю IT и блок? Я пытаюсь выполнить модульное тестирование REjercicioDAO, поэтому я пытаюсь смоделировать зависимость, чтобы я мог тестировать методы изолированно от других внешних объектов.

David Antelo 08.07.2019 20:55

Вы не выполняете Autowire и не запускаете контекст в модульном тесте;)

Maciej Kowalski 08.07.2019 20:56

Думаю, я не понимаю. Почему бы мне не захотеть выполнять автосвязывание, если я тестирую класс с автосвязыванием, для которого мне нужна сущность для выполнения тестов?

David Antelo 08.07.2019 20:58

Возможно, вам действительно нужен модульный тест ... но в этом случае вам не нужны такие вещи, как SpringJUnit4ClassRunner и Autowiring ... вам не нужны какие-либо специфичные для фреймворка вещи в модульном тесте.

Maciej Kowalski 08.07.2019 21:09

Извините, если я глуп, я новичок в тестировании, но разве мне все еще не «нужно» издеваться над сущностями? Мне нужен какой-то способ убедиться, что зависимости в моем коде возвращают некоторые известные значения, чтобы я мог протестировать остальную часть кода изолированно. Если это так, то мне нужен фреймворк, например mockito, или самому создавать фиктивные классы, но я читал, что это не такая уж хорошая идея.

David Antelo 08.07.2019 21:12

Хорошо, я понимаю, что вы имеете в виду, я только что понял, почему мне не нужен контекст или весенние бегуны. Спасибо за терпение хД

David Antelo 08.07.2019 21:17

Другие вопросы по теме