#java #spring-boot #testing #pagination #mockito
#java #spring-boot #тестирование #разбивка на страницы #мокито
Вопрос:
Я пытаюсь протестировать свой метод сохранения в моем классе service impl. В качестве возвращаемого типа у него есть страница. Тест выполнен успешно, но я пишу что-то неправильно, потому что он выполняется для всех случаев, которые обычно не должны, пожалуйста, смотрите Мой код ниже.
Реализация класса обслуживания
@Service
@Transactional
public class CompanyServiceImpl implements CompanyService {
private final CompanyRepository companyRepository;
public CompanyServiceImpl(CompanyRepository companyRepository) {
this.companyRepository = companyRepository;
}
@Override
public Page<Company> findAll(Pageable pageable) {
Page<Company> result = companyRepository.findAll(pageable);
return resu<
}
@Override
public Page<Company> searchCompany(String companyName, Long companyGroupId, Pageable pageable) {
Page<Company> result = companyRepository.findByParametersWeb(companyName,companyGroupId,pageable);
return resu<
}
@Override
public Optional<Company> findById(Long id) {
Optional<Company> entity = companyRepository.findById(id);
return entity;
}
@Override
public Company save(Company company) {
Company entity = companyRepository.save(company);
return entity;
}
@Override
public void delete(Long id) {
companyRepository.deleteById(id);
}
}
Класс службы тестирования
class CompanyServiceImplTest {
@Mock
private CompanyRepository companyRepository;
private CompanyService companyService;
private Company company;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
companyService = new CompanyServiceImpl(companyRepository);
company = new Company();
company.setName("company");
company.setCompanyGroupId(1L);
}
@Test
void searchCompany() {
List<Company> companies = new ArrayList<>();
Pageable pageable= PageRequest.of(0,5);
Page<Company> result = new PageImpl<>(companies,pageable,1);
when(companyRepository.findByParametersWeb(anyString(),anyLong(),any(Pageable.class))).thenReturn(result);
Page<Company> newResult = companyService.searchCompany("giorgos",1L,pageable);
assertEquals(newResult.getTotalElements(),result.getTotalElements());
}
}
Наконец, репозиторий моей компании
@Repository
public interface CompanyRepository extends JpaRepository<Company, Long> {
@Query("SELECT a FROM Company a WHERE (:name is null or ((a.name LIKE :name AND LENGTH(:name) > 0) OR ( a.name = '%')))")
List<Company> findByCompanyName(@Param("name") String name);
@Query("SELECT a FROM Company a WHERE (:name is null or (LENGTH(:name) > 0 "
" AND ((:option = 'yes' AND a.name = :name) or (:option = 'start' AND a.name LIKE CONCAT(:name,'%')) "
" or (:option = 'end' AND a.name LIKE CONCAT('%',:name)) or (a.name LIKE CONCAT('%',:name,'%'))))) "
" AND (:companyGroupId is null or a.companyGroupId = :companyGroupId) ORDER BY a.name")
Page<Company> findByParametersWeb(String name,Long companyGroupId, Pageable pageable);
List<Company> findAllByNameOrderByName();
}
Комментарии:
1. Я не вижу тестового примера, который должен завершиться неудачей. Ваш
searchCompany
тест должен быть успешным, потому что вы говорите mockito, чтобы он имитировал ваш метод репозитория для возвратаresult
страницы. Все, что делает ваш сервис, это возвращает страницу, которую возвращает ваш репозиторий, а затем вы сравниваете ееresult
. Итак, два результата, которые вы сравниваете, являются точно таким же объектом. Можете ли вы опубликовать тестовый пример, который должен завершиться неудачей?2. Итак, Амир, по вашему мнению, что мне изменить?
3. Опубликованный вами код в порядке, в настоящее время я не знаю, в чем заключается ваша реальная проблема
4. если я что-то изменю, например, идентификатор в newResult в 2L, тогда тест снова будет успешным. Разве это обычно не завершится неудачей? потому что есть разные идентификаторы? Я хочу проверить, выполняет ли он поиск правильного объекта
5.
when(companyRepository.findByParametersWeb(anyString(),anyLong(),any(Pageable.class))).thenReturn(result);
в этой строке специально рекомендуется mockito игнорировать любые параметры, которые вы передаете в метод, и всегда возвращатьresult
объект. Так что не имеет значения, вызываете ли выPage<Company> newResult = companyService.searchCompany("giorgos",1L,pageable);
orPage<Company> newResult = companyService.searchCompany("giorgos",2L,pageable);
,newResult
всегда будет тот же объект,result
что и .
Ответ №1:
Итак, здесь вы хотите отличить модульные тесты от интеграционных или компонентных тестов. Ваш тест будет квалифицироваться как модульный тест, он проверяет исключительно функциональность вашего уровня обслуживания, изолированного от всего остального.
Именно поэтому вы издеваетесь над своим уровнем репозитория, чтобы быть независимым от базы данных.
В отличие от этого, интеграционные и компонентные тесты проверяют весь ваш стек приложений.
Для этого должна быть запущена среда загрузки spring, поэтому вы должны аннотировать свой тестовый @ExtendWith(SpringExtension.class)
класс.
Для такого рода тестов вам нужна активная база данных, поэтому обычно вы используете базу данных h2 для своих тестов, которая заполнена данные, предшествующие вашим тестам. Взгляните на это и на это.
В самом тесте вы либо вводите свой сервис и тестируете оттуда, либо вызываете свои конечные точки с помощью RestTemplate
.
@ExtendWith(SpringExtension.class)
@SpringBootTest
@Sql("/schema.sql")
public class DocumentManagementBackendApplicationTest {
@Autowired
private final CompanyServiceImpl companyServiceImpl;
@Test
@Sql("/searchCompany.sql")
public void testSearchCompany() {
List<Company> companies = new ArrayList<>();
Pageable pageable= PageRequest.of(0, 5);
Page<Company> result = companyService.searchCompany("giorgos",1L,pageable);
// now here you know, based on what you insert into your db with your sql scripts,
// what you should expect and so you can test for it
(...)
}
}