Я пытаюсь написать интеграционные тесты для проекта Spring 4 MVC. В проекте я использую Spring Data JPA Repositories и Hibernate.Попытка выполнить интеграционный тест с данными Spring Data JPA Repositories возвращает NullPointerException
Ниже приведены два файла - сам тест интеграции и конфигурация для настройки моей конфигурации Persistence.
PersistenceTestConfiguration.java
package <project>.cms.rest.test.configuration;
import <project>.cms.rest.entity.EntityMarker;
import <project>.cms.rest.repository.RepositoryMarker;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.hibernate3.encryptor.HibernatePBEEncryptorRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackageClasses = {RepositoryMarker.class})
public class PersistenceTestConfiguration {
@Bean
public EntityManagerFactory entityManagerFactory() throws NamingException {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
vendorAdapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setJpaVendorAdapter(vendorAdapter);
factoryBean.setPackagesToScan(EntityMarker.class.getPackage().getName());
factoryBean.setDataSource(dataSource());
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
@Bean
public PlatformTransactionManager transactionManager() throws NamingException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
return transactionManager;
}
@Bean
public HibernateExceptionTranslator exceptionTranslator() {
return new HibernateExceptionTranslator();
}
@Bean
public EmbeddedDatabase dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.H2).build();
}
}
Проблема у меня в том, что, хотя мой классе PersistenceTestConfiguration должен быть инстанцированием соответствующих Хранилищ - они приходят через в классы обслуживания, как нуль.
Если я вручную @Mock репозитории в тестовом классе, то они больше не являются нулевыми в службах, но всегда будут возвращать нуль, например, для вызова метода .save (entity).
Я подозреваю, что я делаю что-то явно глупое, но, похоже, не могу понять.
Любые указатели в правильном направлении были бы любезны.
Edit 1:
Простейшее Возможные испытания
package <project>.cms.rest.test.service;
import <project>.cms.rest.resource.PostalAddressResource;
import <project>.cms.rest.service.PostalAddressService;
import <project>.cms.rest.service.impl.PostalAddressServiceImpl;
import <project>.cms.rest.test.configuration.PersistenceTestConfiguration;
import liquibase.Liquibase;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException;
import liquibase.resource.FileSystemResourceAccessor;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.inject.Inject;
import java.sql.Connection;
@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { PersistenceTestConfiguration.class })
@TestExecutionListeners(mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
public class PostalAddressServiceIntegrationTest {
@InjectMocks
private PostalAddressService postalAddressService = new PostalAddressServiceImpl();
@Inject
private EmbeddedDatabase database;
@Before
public void setupDatabase() throws java.sql.SQLException, LiquibaseException {
MockitoAnnotations.initMocks(this);
Liquibase liquibase = new Liquibase(
"src/liquibase/liquibase-master.xml",
new FileSystemResourceAccessor(),
new JdbcConnection(database.getConnection())
);
liquibase.update("");
}
@After
public void tearDown() throws java.sql.SQLException, LiquibaseException {
Connection connection = database.getConnection();
JdbcConnection liquibaseConnection = new JdbcConnection(connection);
Liquibase liquibase = new Liquibase(
"src/liquibase/liquibase-master.xml",
new FileSystemResourceAccessor(),
liquibaseConnection
);
liquibase.dropAll();
}
@Test
public void testAddNewPostalAddress() {
PostalAddressResource postalAddressResource = new PostalAddressResource();
postalAddressResource.setBuildingNameOrNumber("1");
postalAddressResource.setFirstLine("Test Lane");
postalAddressResource.setSecondLine("Testville");
postalAddressResource.setCountry("Testshire");
postalAddressResource.setPostCode("TE5 7ER");
postalAddressResource.setCountry("United Kingdom");
PostalAddressResource result = postalAddressService.createPostalAddress(postalAddressResource);
Assert.notNull(result);
}
}
Результирующая трассировки стека
java.lang.NullPointerException
at <project>.cms.rest.service.impl.PostalAddressServiceImpl.createPostalAddress(PostalAddressServiceImpl.java:66)
at <project>.cms.rest.test.service.PostalAddressServiceIntegrationTest.testAddNewPostalAddress(PostalAddressServiceIntegrationTest.java:78)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
линии 66 из PostalAddressServiceImpl выглядит следующим образом:
} while(repository.countByPublicId(publicId) > 0);
Edit 2:
Создание теста, который работает непосредственно с репозиторием, а не с помощью службы работает, имея:
@Inject
private PostalAddressRepository repository;
на вершине ведет себя.
Похоже, что @InjectMocks должен подключаться к зависимостям класса Service, что есть проблема, в результате чего репозиторий имеет значение null.
Без трассировки стека трудно сказать что-либо. Имейте один удобный? Кроме того, обычно это помогает сломать пример воспроизведения, чтобы убедиться, что это не одна из десятков штук, которые здесь играют, что вызывает проблему. Эта проблема возникает при загрузке в простой загрузочной репозитории (без всякой безопасности, услуг и т. Д.)? –
@OliverGierke Трассировка стека просто показывает, что репозиторий, используемый службой, является нулевым, когда я вызываю метод на нем. Ничего в коде Spring нет. Я попытаюсь сузить это до одного рабочего примера, но больше нечего раскрыть. –
Извините, но без дополнительной информации или более сжатого примера трудно понять, что происходит не так, как это может быть практически что-нибудь. –