I am trying to write a test for custom spring data repository. I'm also using QueryDSL.
I am new to spring-data. I use spring support for HSQL DB in testing. MySQL for dev.
Problem: I do not see updated data in tests if I use custom repository.
public interface AuctionRepository extends AuctionRepositoryCustom, CrudRepository<Auction, Long>, QueryDslPredicateExecutor<Auction> {
// needed for spring data crud
}
.
public interface AuctionRepositoryCustom {
long renameToBestName();
}
.
public class AuctionRepositoryImpl extends QueryDslRepositorySupport implements AuctionRepositoryCustom {
private static final QAuction auction = QAuction.auction;
public AuctionRepositoryImpl() {
super(Auction.class);
}
#Override
public long renameToBestName() {
return update(auction)
.set(auction.name, "BestName")
.execute();
}
}
My test
Somehow fails at last line
public class CustomAuctionRepositoryImplTest extends AbstractIntegrationTest {
#Inject
AuctionRepository auctionRepository;
#Test
public void testDoSomething() {
Auction auction = auctionRepository.findOne(26L);
assertEquals("EmptyName", auction.getName());
// test save
auction.setName("TestingSave");
auctionRepository.save(auction);
Auction saveResult = auctionRepository.findOne(26L);
assertEquals("TestingSave", saveResult.getName());
// test custom repository
long updatedRows = auctionRepository.renameToBestName();
assertTrue(updatedRows > 0);
Auction resultAuction = auctionRepository.findOne(26L);
assertEquals("BestName", resultAuction.getName()); // FAILS expected:<[BestNam]e> but was:<[TestingSav]e>
}
}
I can't figure out why data doesn't update when using custom repository. If I start application in dev mode, and call renameToBestName() through controller, everything works as expected, name changes.
Below is Test Configuration if needed
#RunWith(SpringJUnit4ClassRunner.class)
#Transactional
#ActiveProfiles("test")
#ContextConfiguration(classes = {TestBeans.class, JpaConfig.class, EmbeddedDataSourceConfig.class})
#ComponentScan(basePackageClasses = IntegrationTest.class, excludeFilters = #Filter({Configuration.class}))
public abstract class AbstractIntegrationTest {
}
.
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackageClasses = Application.class)
class JpaConfig {
#Value("${hibernate.dialect}")
private String dialect;
#Value("${hibernate.hbm2ddl.auto}")
private String hbm2ddlAuto;
#Value("${hibernate.isShowSQLOn}")
private String isShowSQLOn;
#Autowired
private DataSource dataSource;
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setPackagesToScan("auction");
entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties jpaProperties = new Properties();
jpaProperties.put(org.hibernate.cfg.Environment.DIALECT, dialect);
if ( !hbm2ddlAuto.isEmpty()) {
jpaProperties.put(org.hibernate.cfg.Environment.HBM2DDL_AUTO, hbm2ddlAuto);
}
jpaProperties.put(org.hibernate.cfg.Environment.SHOW_SQL, isShowSQLOn);
jpaProperties.put(org.hibernate.cfg.Environment.HBM2DDL_IMPORT_FILES_SQL_EXTRACTOR, "org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor");
entityManagerFactory.setJpaProperties(jpaProperties);
return entityManagerFactory;
}
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
}
This is due to the update query issued through your code is defined to not evict the object potentially touched by the query from the EntityManager. Read more on that in this answer.
Related
I was testing some simple use cases using a CrudRepository and cannot explain the following:
When letting spring auto-configure my application (using #DataJpaTest on my test class + providing properties & schema via application.properties and schema.sql), all entities of my tests are correctly attached to the persistence context and any change is correctly reflected in the database.
However, when I'm providing a custom configuration, they seem to be detached and therefore changes are not reflected.
I came across this comment that mentioned that the context would close after the call to CrudRepository method returns which would explain why are the entities detached but it is then contradictory with my first example.
Could someone explain me what is the difference between the auto config and my programmatic one which would cause this?
Model and repo:
#Entity(name = "contents")
#Table(name = "contents")
public class PersistableContent
{
#Id
#GeneratedValue(generator = "id_generator", strategy = GenerationType.SEQUENCE)
#SequenceGenerator(name = "id_generator", sequenceName = "id_seq", allocationSize=10)
public Integer id;
#Column
public String value;
public PersistableContent() { }
public PersistableContent(String value) { this.value = value; }
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
}
#Repository
public interface PersistableContentRepository extends CrudRepository<PersistableContent, Integer> { }
First test and config (Entity is attached):
#Configuration
#EnableJpaRepositories(basePackages = { "jpa.repositories" })
#EntityScan("jpa.model")
public class MyTestConfiguration { }
#RunWith(SpringRunner.class)
#DataJpaTest
#ContextConfiguration(classes= {MyTestConfiguration.class})
public class PersistableContentRepositoryTest
{
#Autowired
private PersistableContentRepository persistableContentRepository;
#Test
public void updateNewlySavedSupposedlyAttachedEntityTest()
{
PersistableContent toUpdate = new PersistableContent("toUpdate");
persistableContentRepository.save(toUpdate);
toUpdate.setValue("updated");
PersistableContent updated = persistableContentRepository.findById(toUpdate.getId()).get();
assertThat(updated.getValue(), is(equalTo(toUpdate.getValue())));
}
}
Second test and config (Entity is detached and assertion failing):
#Configuration
#EnableJpaRepositories(basePackages = { "jpa.repositories" })
public class MyTestConfiguration
{
#Bean
public DataSource dataSource()
{
DriverManagerDataSource datasource = new DriverManagerDataSource();
datasource.setDriverClassName("org.h2.Driver");
datasource.setUrl("jdbc:h2:mem:default;DB_CLOSE_DELAY=-1");
datasource.setUsername("sa");
datasource.setPassword("sa");
// schema init
Resource initSchema = new ClassPathResource("schema.sql");
DatabasePopulator databasePopulator = new ResourceDatabasePopulator(initSchema);
DatabasePopulatorUtils.execute(databasePopulator, datasource);
return datasource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
JpaVendorAdapter jpaVenderAdapter)
{
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setPackagesToScan("jpa.model");
entityManagerFactoryBean.setJpaVendorAdapter(jpaVenderAdapter);
return entityManagerFactoryBean;
}
#Bean
public JpaVendorAdapter jpaVenderAdapter()
{
return new HibernateJpaVendorAdapter();
}
#Bean
public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory)
{
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory.getObject());
return transactionManager;
}
}
#RunWith(SpringRunner.class)
#Import(MyTestConfiguration.class)
public class PersistableContentRepositoryTest
{
// same test than above, the only difference is that:
// I'm not using #DataJpaTest nor #ContextConfiguration
// I'm importing my Configuration using #Import
}
EDIT:
To understand if it was related to the DataJpaTest auto-configuration, I decided to create another test class annotated with SpringBootTest and I created a new configuration annotated with SpringBootConfiguration. Rerun the same test and this time, the entities are no more attached when retrieved via the repository. I'm wondering if my whole problem is not related to what DataJpaTest does with the test class, something like making every single test as a transaction in order to clean up after each test. If this is the case, it was counter-intuitive for me as I used DataJpaTest in purpose to limit the auto-configuration to only JPA components while still expecting the repository to behave as it would do with a full auto-configuration or with a custom/programmatic one.
I use #EntityListeners to make operations before I save in my Db and after I load.
Inside my Listener class I make a call to an Ecryptor (which needs to fetch info from configuration file), so the encryptor can't be called statically and need to be injected in my Listener. Right?
Well, injections in EntityListeners can't be done straight away, but you have some methods to do that, like using SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); or even the method showed here. https://guylabs.ch/2014/02/22/autowiring-pring-beans-in-hibernate-jpa-entity-listeners/
Cool, the problem is: None of the solutions support unit testing! When running tests that encryptor I had injected in my model Listener is always null.
Here SpringBeanAutowiringSupport does not inject beans in jUnit tests There is a solution to create this context and pass to a instantiated object, but it does not solve my problem since I have the "Injection" to add to it.
Any way to create a context in my tests and somehow pass it to my listeners?
If not, any way I can create a static method to my Encryptor and still have access to the Environment API to read my properties?
Package Listener:
public class PackageListener{
#Autowired
Encryptor encryptor;
#PrePersist
public void preSave(final Package pack){
pack.setBic(encryptor.encrypt(pack.getBic()));
}
...
My test
#Test
#WithuserElectronics
public void testIfCanGetPackageById() throws PackageNotFoundException{
Package pack = packagesServiceFactory.getPackageService().getPackage(4000000002L);
}
Package service
public Package getPackage(Long id) throws PackageNotFoundException{
Package pack = packageDao.find(id);
if (pack == null) {
throw new PackageNotFoundException(id);
}
return pack;
}
Encryptor:
public class Encryptor{
private String salt;
public Encryptor(String salt){
this.salt = salt;
}
public String encrypt(String string){
String key = this.md5(salt);
String iv = this.md5(this.md5(salt));
if (string != null) {
return encryptWithAesCBC(string, key, iv);
}
return string;
}
...
You can create a DemoApplicationContextInitializer class to store the appliationContext reference in a static property in your main class.
public class DemoApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext ac) {
Application.context = ac;
}
}
#SpringBootApplication
public class Application {
public static ApplicationContext context;
public static void main(String[] args) throws Exception {
new SpringApplicationBuilder(Application.class)
.initializers(new DemoApplicationContextInitializer())
.run(args);
}
}
Then you can access the context in your entity listener
public class PackageListener{
//#Autowired
Encryptor encryptor;
#PrePersist
public void preSave(final Package pack){
encryptor = Application.context.getBean(Encryptor.class);
pack.setBic(encryptor.encrypt(pack.getBic()));
}
}
And to make this work in your junit test, just add the initializer in your test like this ...
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT, classes = Application.class)
#ContextConfiguration(classes = Application.class, initializers = DemoApplicationContextInitializer.class)
public class MyTest {
...
}
It works without any issue in my environment. Hope it will be helpful to you too.
To answer what you need, you have to create 2 classes that will do all the configuration needed.
You have to create a testConfig with the next annotations:
#Configuration
#ComponentScan(basePackages = { "yourPath.services.*",
"yourPath.dao.*" })
#EnableAspectJAutoProxy
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "yourPath.dao.entities",
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager",
repositoryBaseClass = Dao.class)
#Import({ DataSourceConfig.class }) //Explained below
public class TestConfig {
#Autowired
private DataSource dataSource;
#Bean
public List<String> modelJPA() {
return Collections.singletonList("es.carm.sms.ortopedia.entities");
}
#Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPackagesToScan(modelJPA().toArray(new String[modelJPA().size()]));
entityManagerFactory.setDataSource(this.dataSource);
JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
return entityManagerFactory;
}
}
Then if you want to connect with your database:
#Configuration
public class DataSourceConfig {
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
dataSource.setUrl("jdbc:oracle:thin:#ip:port:sid");
dataSource.setUsername("name");
dataSource.setPassword("pass");
return dataSource;
}
}
Now you have it all set up, you just need to create your test importing your configurations:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = TestConfig.class)
public class TestCase {...}
You will get your spring context initialized with access to all your resources (MVC) Services, DAO and Model.
I'm writing unit test for an web app, and I've got problem with service layer. App is using Spring Data JPA, and H2 database for tests.
Here is my test class:
#WebAppConfiguration
#ContextConfiguration(classes = {TestConfiguration.class})
#TestPropertySource(locations = "classpath:test.properties")
#Transactional
public class AuthorCreateServiceTest extends AbstractTestNGSpringContextTests {
#Mock
private AuthorRepository authorRepository;
private AuthorCreateServiceImpl authorCreateServiceImpl;
private Author firstAuthor;
private Author secondAuthor;
#BeforeClass
public void setUp() {
authorCreateServiceImpl = new AuthorCreateServiceImpl(authorRepository);
firstAuthor = new Author();
firstAuthor.setFirstName("Leo");
firstAuthor.setLastName("Manly");
firstAuthor.setNationality("Mexico");
firstAuthor.setId(3L);
secondAuthor = new Author();
secondAuthor.setFirstName("Zorro");
secondAuthor.setLastName("Plata");
secondAuthor.setNationality("Zambia");
secondAuthor.setId(4L);
}
#Test
public void succesfullySaveAuthorTest() {
Author testAuthor = authorCreateServiceImpl.create(firstAuthor);
Assert.assertEquals(testAuthor.getFirstName(), firstAuthor.getFirstName());
}
#Test
public void failSavingAuthorTest() {
String firstName = "Man";
Author testAuthor = authorCreateServiceImpl.create(secondAuthor);
boolean isEqual = testAuthor.getFirstName().equals(firstName);
Assert.assertFalse(isEqual);
}
}
In this state testAuthor is null, but repository and createService objects exist. But if I add an Autowired annotation to the AutrhorCreateServiceImpl field, it works fine.
Is the Autowired necessary or I'm doing something wrong?
EDIT
TestConfiguration class
#ComponentScan(basePackages = {"com.altkom.library"} )
#Configuration
#TestPropertySource(locations = "classpath:test.properties")
public class TestConfiguration extends JPAConfiguration {
public TestConfiguration(Environment environment) {
super(environment);
}
#Bean(destroyMethod = "shutdown")
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase dataBase = builder.setType(EmbeddedDatabaseType.H2).addScript("classpath:import.sql").build();
return dataBase;
}
}
If you want to obtain bean from spring-context, this annotation is required.
In your implementation you've created a service with a mocked repository. Mocked objects return null by default. You can use Mockito.when() to override default behaviour.
I have a Spring application and in it I do not use xml configuration, only Java Config. Everything is OK, but when I try to test it I faced problems with enabling autowiring of components in the tests. So let's begin. I have an interface:
#Repository
public interface ArticleRepository extends CrudRepository<Page, Long> {
Article findByLink(String name);
void delete(Page page);
}
And a component/service:
#Service
public class ArticleServiceImpl implements ArticleService {
#Autowired
private ArticleRepository articleRepository;
...
}
I don't want to use xml configurations so for my tests I try to test ArticleServiceImpl using only Java Configuration. So for the test purpose I made:
#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;
}
}
In articleServiceImpl() I need to put instance of articleRepository() but it is an interface. How to create new object with new keyword? Is it possible without creating xml configuration class and enable Autowiring? Can autowired be enabled when using only JavaConfigurations during testing?
This is what I have found is the minimal setup for a spring controller test which needs an autowired JPA repository configuration (using spring-boot 1.2 with embedded spring 4.1.4.RELEASE, DbUnit 2.4.8).
The test runs against a embedded HSQL DB which is auto-populated by an xml data file on test start.
The test class:
#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();
}
}
}
Notes:
#ContextConfiguration annotation which only includes the embedded TestController and the JPA configuration class RepoFactory4Test.
The #TestExecutionListeners annotation is needed in order that the subsequent annotations #DatabaseSetup and #DatabaseTearDown have effect
The referenced configuration class:
#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;
}
}
The UserRepository is a simple interface:
public interface UserRepository extends CrudRepository<EUser, Long>
{
}
The EUser is a simple #Entity annotated class:
#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;
...
}
The FillTestData.xml:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<user id="1"
email="alice#test.org"
...
/>
</dataset>
The DbClean.xml:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<user />
</dataset>
If you're using Spring Boot, you can simplify these approaches a bit by adding #SpringBootTest to load in your ApplicationContext. This allows you to autowire in your spring-data repositories. Be sure to add #RunWith(SpringRunner.class) so the spring-specific annotations are picked up:
#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"));
}
}
You can read more about testing in spring boot in their docs.
You cant use repositories in your configuration class because from configuration classes it finds all its repositories using #EnableJpaRepositories.
So change your Java Configuration to:
#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()
}
If you have many repository implementation classes then create a separate class like below
#Service
public class RepositoryImpl {
#Autowired
private UserRepositoryImpl userService;
}
In your controller Autowire to RepositoryImpl and from there you can access all your repository implementation classes.
#Autowired
RepositoryImpl repository;
Usage:
repository.getUserService().findUserByUserName(userName);
Remove #Repository Annotation in ArticleRepository and ArticleServiceImpl should implement ArticleRepository not ArticleService.
What you need to do is:
remove #Repository from ArticleRepository
add #EnableJpaRepositories to PagesTestConfiguration.java
#Configuration
#ComponentScan(basePackages = {"com.example.core"}) // are you sure you wanna scan all the packages?
#EnableJpaRepositories(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;
}
}
I want to use Spring Data JPA to do the ORM. I have the following declared repository interface:
public interface SegmentRepository extends JpaRepository<Segment, Integer> {
// query methods ...
}
Following is the Java Config class:
#Configuration
#EnableJpaRepositories("com.example.cap.repositories")
#EnableTransactionManagement
public class CAPRepositoryConfig {
#Bean
public DataSource dataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(org.postgresql.Driver.class.getName());
ds.setUsername("postgres");
ds.setPassword("password");
ds.setUrl("jdbc:postgresql://localhost:5432/postgres");
ds.setInitialSize(10);
return ds;
}
#Bean
public EntityManagerFactory entityManagerFactory() {
EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
Map<String, Object> jpaProperties = new HashMap<String, Object>();
jpaProperties.put("eclipselink.weaving", "false");
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.example.cap.repositories");
factory.setDataSource(dataSource());
factory.setJpaPropertyMap(jpaProperties);
factory.afterPropertiesSet();
return factory.getObject();
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
}
And the Segment class is defined in com.example.cap.repositories as:
#Entity
public class Segment {
#Id
private int segmentID;
private int caseID;
private Timestamp segStartTime;
private Timestamp segEndTime;
//setter and getters
}
But when I run the JUnit test using auto injected bean SegmentRepository, I got null point exception for the bean repository:
#ContextConfiguration(classes=CAPRepositoryConfig.class)
public class CAPRepositoryTest {
#Autowired
private SegmentRepository repository;
#Test
public void testRepository() {
Segment seg = repository.findOne(123); //null pointer exception for repository
}
}
According to the Spring Data JPA documentation, the SegmentRepository bean repository should be auto injected as long as I specify #EnableJpaRepositories in the Java Config class. But why do I get null pointer exception for repository in the JUnit test class? Since SegmentRepository is an interface rather than a class, I cannot create the instance through Java Config class.
I think you forget SpringJUnit4ClassRunner which makes #Autowired in tests work:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=CAPRepositoryConfig.class)
public class CAPRepositoryTest { ... }
When I work with test classes and I need to do an unit test, I prefer instantiate the class because although you have an interface you need to have to an implementation class too. In my case I do something like this:
#ContextConfiguration(classes=CAPRepositoryConfig.class)
public class CAPRepositoryTest {
private SegmentRepository repository;
#Before
public void testRepository() {
repository = new SegmentRepositoryImpl();
}
#Test
public void testRepository() {
Segment seg = repository.findOne(123);
}
}