Go with Spring MVC Test
The Spring MVC Test framework provides first class JUnit support for testing client and server-side Spring MVC code through a fluent API. Typically it loads the actual Spring configuration through the TestContext framework and always uses the DispatcherServlet to process requests thus approximating full integration tests without requiring a running Servlet container.
[...] Below is an example of a test requesting account information in JSON format:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("test-servlet-context.xml")
public class ExampleTests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void getAccount() throws Exception {
this.mockMvc.perform(get("/accounts/1").accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.name").value("Lee"));
}
}
Spring MVC test does not distinguishes between components relevant to Spring MVC and your own component classes.
Spring loads and configures every bean it can find in your Spring configuration, including your persistence layer classes.
Testing and persistence.xml
In a spring based application you can omit the persistence.xml in your production and test code completely.
If you can not work without a persistence.xml take a look at these exhaustive explanations done in "How to configure JPA for testing in Maven".
Otherwise take a look at my minimalistic java based configuration that works without a persistence.xml
and either loads the config.properties from src/main/resources or src/test/resources depending on
you are running tests or not (same is possible in xml based configuration, skipped for the sake of brevity).
AppConfig.java
package config;
import org.springframework.context.annotation.*;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@ComponentScan(basePackages = { "myapp" })
@EnableTransactionManagement
@Import(PersistenceJPAConfig.class)
public class AppConfig {
//this bean has to be in the application context if you use property files
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
JPA configuration has a separate configuration class:
PersistenceJPAConfig.java
package config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@PropertySource("classpath:config.properties")
@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig {
@Value("${driverClass}")
private String driverClassName;
@Value("${url}")
private String url;
private boolean jpaGenerateDdl = true;
@Value("${dialect}")
private String hibernateDialect;
@Value("${db.username}")
private String username;
@Value("${db.password}")
private String password;
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan(new String[] { "entities" }); //package wir your annotated jpa entities
final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter() {{
setDatabasePlatform(hibernateDialect);
setGenerateDdl(jpaGenerateDdl);
}
};
factoryBean.setJpaVendorAdapter(vendorAdapter);
return factoryBean;
}
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public JpaTransactionManager transactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
return transactionManager;
}
}
The same is possible with Spring profiles and @ActiveProfile annotation in test classes and @Profile annotation in configuration classes or classes annotated with @Component (@Service, etc).