напоминание
- Test Fixture — фиксированное состояние, используемое в качестве основы для выполнения тестов.
- Модульный тест — эти тесты проверяют, что части кода (компоненты) выполняют некоторые функции, как ожидалось. В среде Java они обычно реализуются на уровне класса.
- Интеграционный тест — Интеграционный тест — это любой тип теста, который проверяет, что набор взаимодействующих компонентов правильно выполняет ожидаемые функции.
конфигурация
Нам нужна конфигурация JPA Hibernate для тестирования в памяти:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
@Configuration @EnableTransactionManagement public class JpaTestConfig { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){ LocalContainerEntityManagerFactoryBean lcemfb = new LocalContainerEntityManagerFactoryBean(); lcemfb.setDataSource( this .dataSource()); lcemfb.setPackagesToScan( new String[] { 'com.jverstry' }); lcemfb.setPersistenceUnitName( 'MyTestPU' ); HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter(); lcemfb.setJpaVendorAdapter(va); Properties ps = new Properties(); ps.put( 'hibernate.dialect' , 'org.hibernate.dialect.HSQLDialect' ); ps.put( 'hibernate.hbm2ddl.auto' , 'create' ); lcemfb.setJpaProperties(ps); lcemfb.afterPropertiesSet(); return lcemfb; } @Bean public DataSource dataSource(){ DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName( 'org.hsqldb.jdbcDriver' ); ds.setUrl( 'jdbc:hsqldb:mem:testdb' ); ds.setUsername( 'sa' ); ds.setPassword( '' ); return ds; } @Bean public PlatformTransactionManager transactionManager(){ JpaTransactionManager tm = new JpaTransactionManager(); tm.setEntityManagerFactory( this .entityManagerFactoryBean().getObject() ); return tm; } @Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){ return new PersistenceExceptionTranslationPostProcessor(); } } |
Нам нужно исключить рабочую конфигурацию из сканирования пакетов (без сканирования com.jverstry):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
@Configuration @ComponentScan (basePackages = { 'com.jverstry.Controller' , 'com.jverstry.DAO' , 'com.jverstry.Item' , 'com.jverstry.Service' }) public class TestConfig { @Bean public MyService getMyService() { return new MyServiceImpl(); } } |
Инструменты весеннего тестирования
- @RunWith — это аннотация JUnit, позволяющая запустить тест с другим бегуном, чем тот, который предоставляется JUnit.
- SpringJUnit4ClassRunner — это бегущий тест JUnit для приложений Spring. Как правило, тестовые классы обозначаются с помощью @RunWith (SpringJUnit4ClassRunner.class).
- @ContextConfiguration — эта аннотация может использоваться, чтобы указать, как загрузить applicationContext в тестовом классе Spring. Это можно настроить с помощью файлов XML или объектов конфигурации Java.
Сервисное тестирование
Следующий класс тестирует метод createAndRetrieve () нашей внедренной реализации MyService:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@RunWith (SpringJUnit4ClassRunner. class ) @ContextConfiguration (classes={ JpaTestConfig. class , TestConfig. class }) public class MyServiceImplTest { @Autowired private MyService myService; @Test public void testCreateAndRetrieve() { MilliTimeItem retr = myService.createAndRetrieve(); assertNotNull(retr); } } |
DAO Testing
Следующий класс тестирует нашу реализацию DAO. Наша реализация внедряется с EntityManager, созданным из нашего тестового класса конфигурации, определенного выше.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
@RunWith (SpringJUnit4ClassRunner. class ) @ContextConfiguration (classes={ JpaTestConfig. class , TestConfig. class }) public class MyPersistenceDAOTest { @Autowired private MyPersistenceDAO myDAO; @Test public void testCreateMilliTimeItem() { // This operation should not throw an Exception long id = myDAO.createMilliTimeItem(); } @Test public void testGetMilliTimeItem() { long id = myDAO.createMilliTimeItem(); MilliTimeItem retr = myDAO.getMilliTimeItem(id); assertNotNull(retr); assertEquals(id,retr.getID()); } } |
Предостережение
Начиная писать тесты JUnit для Spring, можно встретить следующие сообщения об ошибках:
1
2
|
Java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax /validation/Validation |
Вышесказанное часто вызвано следующей зависимостью maven:
1
2
3
4
5
6
|
< dependency > < groupId >javax</ groupId > < artifactId >javaee-api</ artifactId > < version >6.0</ version > < type >jar</ type > </ dependency > |
Следует заменить на:
1
2
3
4
5
6
|
< dependency > < groupId >org.apache.geronimo.specs</ groupId > < artifactId >geronimo-jpa_2.0_spec</ artifactId > < version >1.1</ version > < scope >provided</ scope > </ dependency > |
Другое сообщение об ошибке:
1
|
javax.validation.ValidationException: Unable to find a default provider |
Это решается добавлением следующей зависимости maven:
1
2
3
4
5
|
< dependency > < groupId >org.hibernate</ groupId > < artifactId >hibernate-validator</ artifactId > < version >4.3.0.Final</ version > </ dependency > |
Больше Spring связанных постов здесь .
Ссылка: JUnit Testing Spring Service и DAO (с базой данных в памяти) от нашего партнера JCG Джерома Версринга в блоге технических заметок .