web-dev-qa-db-ja.com

Springでのテスト中にCrudRepositoryインターフェイスのインスタンスを作成するにはどうすればよいですか?

私はSpringアプリケーションを持っていますしないでください xml構成を使用しますJava Config。すべてがOKですが、しようとするとtestテストでコンポーネントの自動配線を有効にする際に問題が発生したので、始めましょう。インターフェース

@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構成を使用したくないので、私のテストではJava構成のみを使用してArticleServiceImplをテストしようとします。したがって、テスト目的で次のようにしました:

@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構成クラスを作成せずに自動配線を有効にすることはできますか?テスト中にJavaConfigurationsのみを使用する場合、自動配線を有効にできますか?

14
Xelian

これは、自動ワイヤードJPAリポジトリー構成が必要なSpringコントローラーテストの最小セットアップです(Spring-Boot 1.2にSpring 4.1.4.RELEASEを組み込み、DbUnit 2.4.8を使用)。

テストは、テスト開始時にxmlデータファイルによって自動入力される埋め込みHSQL DBに対して実行されます。

テストクラス:

@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();
        }
    }
}

ノート:

  • 埋め込まれたTestControllerとJPA構成クラスRepoFactory4Testのみを含む@ContextConfigurationアノテーション。

  • @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="[email protected]"
          ...
    />
</dataset>

DbClean.xml:

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <user />
</dataset>
11
Heri

Spring Bootを使用している場合、ApplicationContextにロードする_@SpringBootTest_を追加することで、これらのアプローチを少し簡略化できます。これにより、Springデータリポジトリで自動配線を行うことができます。 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"));
  }
}
_

スプリングブートでのテストの詳細については、その docs を参照してください。

8
heez

構成クラスから@EnableJpaRepositoriesを使用してすべてのリポジトリを見つけるため、構成クラスでリポジトリを使用することはできません。

  1. 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()  
}
  1. 多くのリポジトリ実装クラスがある場合は、以下のように別のクラスを作成します
@Service
public class RepositoryImpl {
   @Autowired
   private UserRepositoryImpl userService;
}
  1. コントローラで、Autowire to RepositoryImplにアクセスして、そこからすべてのリポジトリ実装クラスにアクセスできます。
@Autowired
RepositoryImpl repository;

使用法:

repository.getUserService()。findUserByUserName(userName);

ArticleRepositoryの@Repositoryアノテーションを削除し、ArticleServiceImplはArticleServiceではなくArticleRepositoryを実装する必要があります。

1
sagar

あなたがする必要があるのは:

  1. 削除する @RepositoryArticleRepositoryから

  2. 追加 @EnableJpaRepositoriesから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;
    }
    }
    
0
Jaiwo99