Я использую 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);
...
}
Кстати, сущности работают так, как ожидалось, и интерфейсы правильно связаны с реальными сущностями, я это проверял. Как я могу это исправить?




Вот нет ответа. Я не мог бы дать больше, потому что мне очень жаль видеть, что так много людей используют этот неуклюжий 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);
}
}
Спасибо, я думаю, что я просто буду использовать сеттер для зависимости, потому что это проще, чем иметь дело с конфигурацией и интеграцией библиотеки.
Нет: спасибо вам за то, что вы изменили свой подход! Легче, а также действительно яснее!
Вы пытаетесь смешать ИТ с модульным тестом.
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, поэтому я пытаюсь смоделировать зависимость, чтобы я мог тестировать методы изолированно от других внешних объектов.
Вы не выполняете Autowire и не запускаете контекст в модульном тесте;)
Думаю, я не понимаю. Почему бы мне не захотеть выполнять автосвязывание, если я тестирую класс с автосвязыванием, для которого мне нужна сущность для выполнения тестов?
Возможно, вам действительно нужен модульный тест ... но в этом случае вам не нужны такие вещи, как SpringJUnit4ClassRunner и Autowiring ... вам не нужны какие-либо специфичные для фреймворка вещи в модульном тесте.
Извините, если я глуп, я новичок в тестировании, но разве мне все еще не «нужно» издеваться над сущностями? Мне нужен какой-то способ убедиться, что зависимости в моем коде возвращают некоторые известные значения, чтобы я мог протестировать остальную часть кода изолированно. Если это так, то мне нужен фреймворк, например mockito, или самому создавать фиктивные классы, но я читал, что это не такая уж хорошая идея.
Хорошо, я понимаю, что вы имеете в виду, я только что понял, почему мне не нужен контекст или весенние бегуны. Спасибо за терпение хД
Предполагаю: аннотация с автоматическим подключением в тестовом коде... Попробуйте удалить ее. Я весьма сомневаюсь, что размещение двух подобных аннотаций на одном и том же поле принесет какую-либо пользу.