Junit, Mockito и Querydsl (Mysema) для издевательства над JPAQueryFactory
Я пытаюсь настроить модульный тест для метода приложения Spring Boot, использующего библиотеку Querydsl (Mysema). Тестируемый метод включает следующие строки кода:
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QEntity q = QEntity.entity;
long count = queryFactory.from(q)
.select(q.anInteger)
.where(aBooleanExpression)
.fetchCount();
В классе модульного теста я пишу метод настройки, аннотированный @Before, где я делаю следующее:
JPAQueryFactory queryFactory = Mockito.mock(JPAQueryFactory.class, Mockito.RETURNS_DEEP_STUBS);
QEntity q = QEntity.etity;
BooleanExpression aBooleanExpression = ... // The same as used in the method under test
Mockito
.when(((JPAQuery<Integer>) queryFactory
.from(q)
.select(q.anInteger))
.where(aBooleanExpression)
.fetchCount()
).thenReturn(1L);
Нет ошибок компиляции, но когда я запускаю тест, получаю исключение:
java.lang.ClassCastException: com.querydsl.core.support.QueryBase$$EnhancerByMockitoWithCGLIB$$6824f47d cannot be cast to com.querydsl.jpa.impl.JPAQuery
Я не знаю, каким образом я должен рефрактировать предыдущий код, чтобы он работал.
2 ответа
Каждый объект возврата вызова
queryFactory.from(q)
.select(q.anInteger))
.where(aBooleanExpression)
.fetchCount()
в вашем случае вы должны издеваться шаг за шагом:
JPAQuery step1 = Mockito.mock(JPAQuery.class);
Mockito.when(queryFactory.from(q)).thenReturn(step1);
JPAQuery step2 = Mockito.mock(JPAQuery.class);
Mockito.when(step1.select(q.anInteger)).thenReturn(step2);
JPAQuery step3 = Mockito.mock(JPAQuery.class);
Mockito.when(step2.where(aBooleanExpression)).thenReturn(step3);
... и так далее
Не уверен насчет класса возвращаемого объекта, пожалуйста, проверьте, это пример только для объяснений.
Я столкнулся с этой проблемой с Springboot unitest, мой запрос
List<TaxiEntity> taxiEntities = queryFactory.selectFrom(qTaxiEntity)
.innerJoin(qTaxiEntity.callMe, qDriver)
.where(qTaxiEntity.abcId.eq(abcId))
.limit(pageable.getPageSize())
.offset(pageable.getOffset())
.fetch();
мой модульный тест для издевательства над этим запросом. Он работает успешно
@Mock
private JPAQueryFactory queryFactory;
@Test
public void testBanana() {
.....
JPAQuery jpaQuery = Mockito.mock(JPAQuery.class);
when(queryFactory.selectFrom(any())).thenReturn(jpaQuery);
when(jpaQuery.select(any(Expression.class))).thenReturn(jpaQuery);
when(jpaQuery.innerJoin((EntityPath) any(), any())).thenReturn(jpaQuery);
when(jpaQuery.where(any(BooleanExpression.class))).thenReturn(jpaQuery);
when(jpaQuery.limit(anyLong())).thenReturn(jpaQuery);
when(jpaQuery.offset(anyLong())).thenReturn(jpaQuery);
when(jpaQuery.fetch()).thenReturn(resultList);
....
}