Я пытаюсь проверить интерфейс службы, который имеет указанную реализацию в TestConfiguration. Сервисный интерфейс получает интерфейс DAO, который также имеет указанную реализацию в TestConfiguration. Реализация Службы определяется как реальная служба, которая будет работать, в то время как Test DAO - это новая пользовательская реализация интерфейса.
В 95% случаев я хочу использовать тестовую реализацию DAO. Однако в некоторых тестах я хочу переопределить функциональность DAO. Поскольку существует так мало случаев, когда я хочу переопределить DAO, я хочу просто имитировать использование Mockito на условной основе, не создавая другую реализацию интерфейса DAO (для крайних случаев, таких как возврат пустого списка из DAO). В идеале они должны быть в том же классе, который предназначен для тестирования Сервиса.
Я попытался использовать аннотацию @Spy для компонента DAO в классе тестирования. Я пытался использовать @MockBean для компонента DAO. Однако я попытался использовать doReturn от Mockito и, когда функциональность перезаписывает реализацию DAO по умолчанию, я всегда получаю результат от реализации Test DAO, определенной в TestConfiguration.
Я изменил текст того, что я делаю, так как это код компании, но это именно то, что я пытаюсь сделать иначе.
Моя TestConfiguration определена так
@TestConfiguration
public class TestAppConfiguration {
@Bean
public PersonService personService() {
return new PersonServiceImpl(personDao());
}
@Bean
public PersonDao personDao() {
return new TestPersonDaoImpl();
}
}
Моя реализация сервиса выглядит следующим образом
public class PersonServiceImpl implements PersonService {
private Logger logger = LoggerFactory.getLogger(PersonServiceImpl.class);
private PersonDao personDao;
public PersonServiceImpl(PersonDao personDao){
this.personDao = personDao;
}
@Override
public List<PersonDto> getAllPersons() {
return personDao.findAll().stream()
.map(person -> PersonDtoFactory.getPersonDto(person))
.collect(Collectors.toList());
}
@Override
public PersonDto getPersonById(Long id) {
return PersonDtoFactory.getPersonDto(personDao.findById(id));
}
}
Моя тестовая реализация DAO выглядит следующим образом
public class TestPersonDaoImpl implements PersonDao {
@Override
public List<PersonModel> findAll() {
return getPersons();
}
@Override
public List<PersonModel> findById(id) {
return getPersons().stream()
.filter(person -> person.getId() == id)
.collect(Collectors.toList());
}
private List<PersonModel> getPersons() {
List<PersonModel> personList = new ArrayList<>();
personList.add(new PersonModel(1L, "Susan");
personList.add(new PersonModel(2L, "Jerry");
personList.add(new PersonModel(3L, "Tom");
return personList;
}
}
И вот, наконец, мой тестовый класс обслуживания
@RunWith(SpringRunner.class)
@Import(TestAppConfiguration.class)
public class PersonServiceTests {
//We won't test web socket functionality in this test class.
@Autowired
private PersonService personService;
@MockBean //want to overwrite in the test only when specified in the test, otherwise, use default TestPersonDaoImpl bean.
private PersonDao personDao;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void getAllPersons() {
assert(personService.getAllTests().size() > 0);
}
@Test
public void getPersonById() {
assert(personService.getPersonById(1L).getName().equals("Susan"));
}
@Test
public void getAllPersons_NoPersons(){
//Mock the DAO call since it will have all of the test data by default
doReturn(new ArrayList<Person>()).when(personDao).findAll();
//when(personDao.findAll()).thenReturn(new ArrayList<>()); <-- this also doesn't work
assert(personService.getAllPersons().size() == 0);
}
Ожидается, что все тесты пройдут, и вызов DAO будет перезаписан при вызове в реализации сервиса. Фактическим результатом является то, что первые два теста пройдены, а третий тест не пройден, поскольку он не перезаписывает вызов dao.