2012-02-08 5 views
2

У меня есть особенно противный проверки (JMock) блок для запроса JPA, что я хочу перейти на Mockito:Mock JPA CriteriaBuilder с Mockito

Mockery jMock = new Mockery(); 
final EntityManager fakeEntityManager = jMock.mock(EntityManager.class); 
final CriteriaBuilder fakeCriteriaBuilder = jMock.mock(CriteriaBuilder.class); 
final CriteriaQuery<String> fakeCriteriaQuery = jMock.mock(CriteriaQuery.class); 
jMock.checking(new Expectations() {{ 
    oneOf(fakeEntityManager).getCriteriaBuilder(); will(returnValue(fakeCriteriaBuilder)); 
    oneOf(fakeCriteriaBuilder).createQuery(String.class); will(returnValue(fakeCriteriaQuery)); 
    oneOf(fakeCriteriaQuery).from(Archiveusergrouplicences.class); 
    oneOf(fakeCriteriaQuery).select(with(any(Selection.class))); 
    oneOf(fakeCriteriaBuilder).isNotNull(with(any(Expression.class))); 
    oneOf(fakeCriteriaQuery).where(with(any(Expression.class))); 
    oneOf(fakeEntityManager).createQuery(fakeCriteriaQuery); 
    // Return an empty resultset 
}}); 

код протестированный выглядит следующим образом:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<String> criteria = builder.createQuery(String.class); 

Root<Archiveusergrouplicences> institution = criteria.from(Archiveusergrouplicences.class); 
criteria.select(institution.get(Archiveusergrouplicences_.usergroupid));  
criteria.where(builder.isNotNull(institution.get(Archiveusergrouplicences_.usergroupid))); 

List<String> result = entityManager.createQuery(criteria).getResultList(); 

Я нашел this question on mocking builders, что в какой-то мере решает проблему CriteriaBuilder; но моя основная проблема заключается в использовании издевающихся объектов как значение .thenReturn() другого макета - Mockito, похоже, не позволяет этого. Например, для линии:

CriteriaQuery<String> criteria = builder.createQuery(String.class); 

Я хочу вернуть фиктивный объект CriteriaQuery, как это:

CriteriaQuery<String> fakeCriteriaQuery = mock(CriteriaQuery.class, RETURNS_DEEP_STUBS); 
when(entityManager.createQuery(anyString())).thenReturn(fakeCriteriaQuery); 

Это вызывает ошибку синтаксиса:

The method thenReturn(Query) in the type OngoingStubbing is not applicable for the arguments (CriteriaQuery)

Как я мог бы пойти о тестировании этого кода или его улучшении, чтобы сделать его более проверяемым?

+2

Вопрос, который я задал себе, заключается в том, что высмеивать весь ORM действительно стоит того, или просто проще использовать его, например, база данных в памяти для тестирования. http://www.dbunit.org/ оказался полезным для этого и в прошлом. –

+0

Все остальные тесты являются функциональными (с использованием тестовой базы данных и чего-то подобного dbunit). Цель теста, который я переношу, кажется, утверждает, что когда возникает непредвиденное исключение, DAO возвращает исключение NoResultsException для вызывающего. Я думаю, что это исключение зависит от сценариев, таких как база данных, сходящаяся во время запроса, или в случае тестирования: NPE возвращается структурой JPA. – seanhodges

+0

Вдохновение в тест, возможно, лучший способ его написать. Использование теста func и удаление таблицы перед выполнением запроса может быть лучшим подходом, чем принудительное использование NPE. – seanhodges

ответ

1

Оказывается, вы можете вернуть издевается из других издевается - до тех пор, как вы установите правильные аргументы! Я пытался утверждать:

when(entityManager.createQuery(anyString())).thenReturn(fakeCriteriaQuery); 

Когда то, что я на самом деле хотел было пройти в классе:

when(fakeCriteriaBuilder.createQuery(String.class)).thenReturn(fakeCriteriaQuery); 

Ошибка была загадочным образом Mockito хочет сказать мне, что я испортил мои ожидания.

Тем не менее, я могу пересмотреть этот тест, а не перевести то, что изначально было написано. Как указывали некоторые из них; часто бывает лучше избегать насмешек в библиотеках таким образом, и проверяемое условие довольно расплывчато.

+1

У Mockito есть ответ по умолчанию, называемый «RETURNS_DEEP_STUBS», хотя он не очень полезен для API-интерфейса построителя. Также ложный возврат макета, как тестовый запах, вы слишком много связываете с вашим модульным тестом с помощью метода имплантации, это тестирование белого ящика! Я настоятельно рекомендую вам подумать об интеграции, например, с H2. Антонио Гонсалвес, член эксперта JSR из JAA, написал интересные статьи по этому вопросу http://agoncal.wordpress.com/2012/01/16/wytiwyr-what-you-test-is-what-you-run/ – Brice

0

Как ты JMock CriteriaQuery

final CriteriaQuery<String> fakeCriteriaQuery = jMock.mock(CriteriaQuery.class); 

Вы должны Mockito CriteriaQuery слишком

final CriteriaQuery<String> fakeCriteriaQuery = mock(CriteriaQuery.class); 
+1

Небольшое напоминание от насмешливого сообщества: ** [Не придумывайте типы, которыми вы не являетесь!] (Http://www.google.fr/search?q=don't%20mock%20type%20you%20don ' t% 20own) ** Вместо этого напишите интеграционные тесты! – Brice

+0

@Brice: Спасибо за этот указатель. Как я указал в своем комментарии к самому вопросу, я чувствовал, что это была плохая идея. Теперь у меня есть некоторые ссылки, чтобы поддержать это чувство. Еще раз спасибо! –

+0

иногда не может сделать это в модульном тесте, не так ли? –

Смежные вопросы