Как сделать экземпляр интерфейса CrudRepository во время тестирования весной?
у меня весна приложение, и в нем я не используйте конфигурацию xml, только Java Condfig. Все в порядке, но когда я пытаюсь тест это я столкнулся с проблемами с включением awtowiring компонентов в тестах. Итак, давайте начнем у меня есть интерфейс
@Repository
public interface ArticleRepository extends CrudRepository<Page, Long> {
Article findByLink(String name);
void delete(Page page);
}
и компонент/сервис
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleRepository articleRepository;
...
}
Я не хочу использовать конфигурации xml, поэтому для моих тестов я пытаюсь протестировать ArticleServiceImpl, используя только Java Конфигурация. Поэтому для тестовой цели я сделал:
@Configuration
@ComponentScan(basePackages = {"com.example.core", "com.example.repository"})
public class PagesTestConfiguration {
@Bean
public ArticleRepository articleRepository() {
// (1) What to return ?
}
@Bean
public ArticleServiceImpl articleServiceImpl() {
ArticleServiceImpl articleServiceImpl = new ArticleServiceImpl();
articleServiceImpl.setArticleRepository(articleRepository());
return articleServiceImpl;
}
}
на articleServiceImpl () мне нужно поставить экземпляр articleRepository (), но это интерфейс. Как создать новый объект с новым ключевым словом? Возможно ли это без создания класса конфигурации xml и включения автозапуска? Можно ли включить awtowired при использовании только JavaConfigurations во время тестирования?
4 ответов
это то, что я нашел,-это минимальная настройка Для теста spring controller, который нуждается в конфигурации репозитория JPA autowired (используя spring-boot 1.2 со встроенной пружиной 4.1.4.Освобождения, д. Банкрофт 2.4.8).
тест выполняется против встроенной базы данных HSQL, которая автоматически заполняется XML-файлом данных при запуске теста.
тест класс:
@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( classes = { TestController.class,
RepoFactory4Test.class } )
@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionDbUnitTestExecutionListener.class } )
@DatabaseSetup( "classpath:FillTestData.xml" )
@DatabaseTearDown( "classpath:DbClean.xml" )
public class ControllerWithRepositoryTest
{
@Autowired
private TestController myClassUnderTest;
@Test
public void test()
{
Iterable<EUser> list = myClassUnderTest.findAll();
if ( list == null || !list.iterator().hasNext() )
{
Assert.fail( "No users found" );
}
else
{
for ( EUser eUser : list )
{
System.out.println( "Found user: " + eUser );
}
}
}
@Component
static class TestController
{
@Autowired
private UserRepository myUserRepo;
/**
* @return
*/
public Iterable<EUser> findAll()
{
return myUserRepo.findAll();
}
}
}
Примечания:
@ContextConfiguration аннотация, которая включает только встроенный TestController и класс конфигурации JPA RepoFactory4Test.
аннотация @TestExecutionListeners необходима для того, чтобы последующие аннотации @DatabaseSetup и @DatabaseTearDown имели эффект
ссылочный класс конфигурации:
@Configuration
@EnableJpaRepositories( basePackageClasses = UserRepository.class )
public class RepoFactory4Test
{
@Bean
public DataSource dataSource()
{
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType( EmbeddedDatabaseType.HSQL ).build();
}
@Bean
public EntityManagerFactory entityManagerFactory()
{
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl( true );
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter( vendorAdapter );
factory.setPackagesToScan( EUser.class.getPackage().getName() );
factory.setDataSource( dataSource() );
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public PlatformTransactionManager transactionManager()
{
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory( entityManagerFactory() );
return txManager;
}
}
UserRepository представляет собой простой интерфейс:
public interface UserRepository extends CrudRepository<EUser, Long>
{
}
EUser-это простой аннотированный класс @Entity:
@Entity
@Table(name = "user")
public class EUser
{
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
@Max( value=Integer.MAX_VALUE )
private Long myId;
@Column(name = "email")
@Size(max=64)
@NotNull
private String myEmail;
...
}
в FillTestData.XML-код:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<user id="1"
email="alice@test.org"
...
/>
</dataset>
В DbClean.XML-код:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<user />
</dataset>
если вы используете Spring Boot, вы можете немного упростить эти подходы, добавив @SpringBootTest
для загрузки в ваш ApplicationContext
. Это позволяет автоматически подключаться к хранилищам spring-данных. Обязательно добавьте @RunWith(SpringRunner.class)
таким образом, весной конкретные аннотации подобраны:
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrphanManagementTest {
@Autowired
private UserRepository userRepository;
@Test
public void saveTest() {
User user = new User("Tom");
userRepository.save(user);
Assert.assertNotNull(userRepository.findOne("Tom"));
}
}
вы можете узнать больше о тестировании в spring boot в их docs.
вы не можете использовать репозитории в своем классе конфигурации, потому что из классов конфигурации он находит все свои репозитории с помощью @EnableJpaRepositories.
- поэтому измените конфигурацию Java на:
@Configuration @EnableWebMvc @EnableTransactionManagement @ComponentScan("com.example") @EnableJpaRepositories(basePackages={"com.example.jpa.repositories"})//Path of your CRUD repositories package @PropertySource("classpath:application.properties") public class JPAConfiguration { //Includes jpaProperties(), jpaVendorAdapter(), transactionManager(), entityManagerFactory(), localContainerEntityManagerFactoryBean() //and dataSource() }
- если у вас много классов реализации репозитория, создайте отдельный класс, как показано ниже
@Service public class RepositoryImpl { @Autowired private UserRepositoryImpl userService; }
- в вашем контроллере Autowire для RepositoryImpl и от там вы можете получить доступ ко всем классам реализации репозитория.
@Autowired RepositoryImpl repository;
использование:
репозитория.getUserService ().findUserByUserName (имя пользователя);
удалить аннотацию @Repository в ArticleRepository и ArticleServiceImpl должны реализовать ArticleRepository не ArticleService.
что вам нужно сделать, это:
удалить
@Repository
СArticleRepository
-
добавить
@EnableJpaRepositories
toPagesTestConfiguration.java
@Configuration @ComponentScan(basePackages = {"com.example.core"}) // are you sure you wanna scan all the packages? @EnableJapRepository(basePackageClasses = ArticleRepository.class) // assuming you have all the spring data repo in the same package. public class PagesTestConfiguration { @Bean public ArticleServiceImpl articleServiceImpl() { ArticleServiceImpl articleServiceImpl = new ArticleServiceImpl(); return articleServiceImpl; } }