在测试运行时部分模拟Spring Bean

3df52oht  于 2024-01-05  发布在  Spring
关注(0)|答案(1)|浏览(165)

我的Sping Boot v3.2.0应用程序包含一个LocalContainerEntityManagerFactoryBean类型的bean。当测试运行时,我希望此bean的destroy方法(在父类AbstractEntityManagerFactoryBean中定义)不执行任何操作。我尝试使用

  1. import static org.mockito.Mockito.doNothing;
  2. // other imports omitted
  3. @SpringBootTest
  4. public class MyIntegrationTests {
  5. @SpyBean
  6. private AbstractEntityManagerFactoryBean entityManagerFactoryBean;
  7. @Test
  8. void myIntegrationTest() {
  9. doNothing().when(entityManagerFactoryBean).destroy();
  10. // remainder of test omitted
  11. }
  12. }

字符串
但是当我运行测试时,我得到了这个错误,它表明没有为entityManagerFactoryBean创建间谍程序

  1. org.mockito.exceptions.misusing.NotAMockException:
  2. Argument passed to when() is not a mock!


即使这个解决方案确实有效,我也不会对它完全满意,因为没有明显的方法可以在其他集成测试类中重用它(除了复制粘贴)。
当测试运行时,是否有其他方法可以存根此bean的destroy方法?

最小可复制示例

通过克隆this GitHub repository并运行./gradlew test可以重现此问题

0yycz8jy

0yycz8jy1#

这与Spring如何示例化EntityManagerFactory有关。你必须使用这样的东西:

  1. @SpyBean(name = "entityManagerFactory", classes = EntityManagerFactory.class)
  2. private Object entityManagerFactoryBean;

字符串
不幸的是,你会发现bean的运行时类型是一个不扩展AbstractEntityManagerFactoryBean的代理(参见AbstractEntityManagerFactoryBean::createEntityManagerFactoryProxy),并且访问代理的delegate字段涉及到打开内部模块,这不是一个好主意。
因此,我建议将现有的EntityManagerFactory Package 在一个代理中,并拦截destroy()方法。为此,要么使用lombok和@Delegate来避免手动编写每个委托方法,要么使用CGLib在类上生成一个动态代理(见下文)。在测试类中添加以下内容可以实现您想要的功能:

  1. @TestConfiguration
  2. static class Config {
  3. @Bean
  4. BeanPostProcessor beanPostProcessor() {
  5. return new BeanPostProcessor() {
  6. @Override
  7. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  8. if (bean instanceof AbstractEntityManagerFactoryBean factoryBean) {
  9. return Enhancer.create(bean.getClass(),
  10. (InvocationHandler) (proxy, method, args) -> {
  11. if (method.getName().equals("destroy")) {
  12. System.out.println("not destroying!");
  13. return null;
  14. } else {
  15. return method.invoke(factoryBean, args);
  16. }
  17. });
  18. }
  19. return bean;
  20. }
  21. };
  22. }
  23. }

展开查看全部

相关问题