簡體   English   中英

@EntityListeners注入+ jUnit測試

[英]@EntityListeners Injection + jUnit Testing

在我保存到Db之后和加載之后,我使用@EntityListeners來進行操作。 在我的Listener類中,我調用了一個Ecryptor (需要從配置文件中獲取信息),因此加密器不能靜態調用,需要在我的Listener中注入。 對?

好吧,EntityListeners中的注入不能馬上完成,但你有一些方法可以做到這一點,比如使用SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 甚至這里顯示的方法。 https://guylabs.ch/2014/02/22/autowiring-pring-beans-in-hibernate-jpa-entity-listeners/

很酷,問題是:沒有一個解決方案支持單元測試! 當運行我在模型中注入的加密器測試時,Listener始終為null

這里SpringBeanAutowiringSupport不會在jUnit測試中注入bean有一個解決方案來創建這個上下文並傳遞給實例化的對象,但它沒有解決我的問題,因為我有“注入”添加到它。

在我的測試中創建上下文的任何方式,並以某種方式將其傳遞給我的聽眾? 如果沒有,我可以通過任何方式為我的加密器創建一個靜態方法,並且仍然可以訪問Environment API來讀取我的屬性嗎?

包偵聽器:

public class PackageListener{
   @Autowired
   Encryptor encryptor;

   @PrePersist
   public void preSave(final Package pack){
      pack.setBic(encryptor.encrypt(pack.getBic()));
   }
   ...

我的考試

 @Test
 @WithuserElectronics
 public void testIfCanGetPackageById() throws PackageNotFoundException{
     Package pack = packagesServiceFactory.getPackageService().getPackage(4000000002L);
 }

套餐服務

  public Package getPackage(Long id) throws PackageNotFoundException{
    Package pack = packageDao.find(id);

    if (pack == null) {
        throw new PackageNotFoundException(id);
    }

    return pack;
}

加密:

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;
    }
    ...

要回答您的需求,您必須創建2個類,這些類將執行所需的所有配置。

您必須使用下一個注釋創建testConfig:

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

然后,如果要連接數據庫:

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

}

現在您已完成所有設置,您只需創建導入配置的測試:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
public class TestCase {...}

您將通過訪問所有資源(MVC)服務,DAO和模型來初始化您的spring上下文。

您可以創建一個DemoApplicationContextInitializer類存儲appliationContext在主類的靜態屬性的參考。

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

然后,您可以訪問實體偵聽器中的上下文

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

要在junit測試中完成這項工作,只需在測試中添加初始化程序,就像這樣......

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT, classes = Application.class)
@ContextConfiguration(classes = Application.class, initializers = DemoApplicationContextInitializer.class)
public class MyTest {
...
}

它在我的環境中沒有任何問題。 希望它對你也有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM