@EntityListeners注入+ jUnit测试


问题内容

我使用@EntityListeners,使操作之前我在DB和之后我负载保存。在我的侦听器类中,我调用了Ecryptor(需要从配置文件中获取信息),因此不能静态调用加密器,而需要将其注入到我的侦听器中。对?

好吧,无法立即完成EntityListeners中的注入,但是您可以使用某些方法来做到这一点,例如使用SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);甚至此处显示的方法。https://guylabs.ch/2014/02/22/autowiring-
pring-beans-in-hibernate-jpa-entity-
listeners/

很酷,问题是:没有任何解决方案支持单元测试!在运行我在模型中注入的加密程序的测试时,Listener始终为null

这里,SpringBeanAutowiringSupport不会在jUnit测试中注入bean。存在一种创建此上下文并将其传递给实例化对象的解决方案,但是由于我要添加“注入”,因此它无法解决我的问题。

有什么方法可以在测试中创建上下文并将其以某种方式传递给我的听众?如果没有,是否可以以某种方式为我的Encryptor创建一个静态方法,并且仍然可以访问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;
    }
    ...

问题答案:

您可以创建一个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 {
...
}

在我的环境中,它可以正常工作。希望对您也有帮助。