Ich habe eine Spring-Anwendung und darin verwende ich nicht die XML-Konfiguration, nur Java Condfig. Alles ist in Ordnung, aber als ich versuchte, test es zu machen, hatte ich Probleme damit, ein Verdrahten der Komponenten in den Tests zu ermöglichen. Also fangen wir an, ich habe ein interface
@Repository
public interface ArticleRepository extends CrudRepository<Page, Long> {
Article findByLink(String name);
void delete(Page page);
}
Und eine Komponente/Dienstleistung
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleRepository articleRepository;
...
}
Ich möchte keine XML-Konfigurationen verwenden, daher versuche ich, ArticleServiceImpl für meine Tests nur mit Java Configuration zu testen. Also für den Testzweck habe ich gemacht:
@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 () muss ich eine Instanz von articleRepository () einfügen, aber es ist eine Schnittstelle. Wie erstelle ich ein neues Objekt mit einem neuen Schlüsselwort? Ist es möglich, ohne XML-Konfigurationsklasse zu erstellen und Autowiring zu aktivieren? Kann awtowired aktiviert werden, wenn beim Testen nur JavaConfigurations verwendet werden?
Dies ist, was ich gefunden habe, die minimale Einrichtung für einen Federkontrollertest, für den eine automatische JPA-Repository-Konfiguration erforderlich ist (unter Verwendung des Federstiefels 1.2 mit eingebetteter Feder 4.1.4.RELEASE, DbUnit 2.4.8).
Der Test wird mit einer eingebetteten HSQL-Datenbank ausgeführt, die beim Teststart von einer XML-Datendatei automatisch aufgefüllt wird.
Die Testklasse:
@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();
}
}
}
Anmerkungen:
@ContextConfiguration-Annotation, die nur den eingebetteten TestController und die JPA-Konfigurationsklasse RepoFactory4Test enthält.
Die Annotation @TestExecutionListeners ist erforderlich, damit die nachfolgenden Annotationen @DatabaseSetup und @DatabaseTearDown wirksam werden
Die referenzierte Konfigurationsklasse:
@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;
}
}
Das UserRepository ist eine einfache Schnittstelle:
public interface UserRepository extends CrudRepository<EUser, Long>
{
}
Der EUser ist eine einfache, mit @Entity versehene Klasse:
@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;
...
}
Die FillTestData.xml:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<user id="1"
email="[email protected]"
...
/>
</dataset>
Die DbClean.xml:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<user />
</dataset>
Wenn Sie Spring Boot verwenden, können Sie diese Ansätze ein wenig vereinfachen, indem Sie @SpringBootTest
hinzufügen, um sie in Ihre ApplicationContext
zu laden. Auf diese Weise können Sie Ihre Quelldaten-Repositories automatisch abwickeln. Stellen Sie sicher, dass Sie @RunWith(SpringRunner.class)
hinzufügen, damit die frühlingsspezifischen Anmerkungen aufgenommen werden:
@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"));
}
}
Weitere Informationen zum Testen von Spring Boot finden Sie in docs .
Sie können keine Repositorys in Ihrer Konfigurationsklasse verwenden, da von den Konfigurationsklassen aus alle @ Repositorys mit @EnableJpaRepositories gefunden werden.
@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; }
@Autowired RepositoryImpl repository;
Verwendungszweck:
repository.getUserService (). findUserByUserName (Benutzername);
Entfernen Sie @Repository-Annotation in ArticleRepository und ArticleServiceImpl sollte ArticleRepository und nicht ArticleService implementieren.
Was Sie tun müssen, ist:
@Repository
aus ArticleRepository
entfernen
@EnableJpaRepositories
zu PagesTestConfiguration.Java
hinzufügen
@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;
}
}