如何在springboot集成测试中有效地调用bean的destroy方法?

时间:2016-10-19 16:21:18

标签: spring spring-boot spring-test

我的配置类如下所示:

@SpringBootApplication
public class Application {
    @Bean(destroyMethod = "close")
    public CassandraClient cassandraClient() { ... }
}

我的CassandraClient类有一个close()方法,当应用程序上下文关闭时会调用该方法(我通过步骤调试看到它)。但是,我无法找到一种方法来测试close()方法是否被有效调用。

以下是我想测试的内容:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ContextConfiguration(classes = { Application.class })
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class ApplicationIntegrationTests implements ApplicationContextAware {

    ApplicationContext applicationContext;

    @Autowired
    CassandraClient cassandraClient;

    @Test
    public void cassandraClientCloseIsCalled() {
       ((ConfigurableApplicationContext)applicationContext).close();
       // How can I check that cassandraClient.close() has been called once ?
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

我尝试在配置类中添加一个方面来进行计数,但我无法获得与close方法匹配的切入点。好像我的方面在cassandraClient bean之前被破坏了。

1 个答案:

答案 0 :(得分:1)

我看到这个问题已经存在一段时间了,我调查了这个问题并找到了一个适合我的解决方案。您可以在此处查看:Testing Nuts Example。本质上,杏仁是我使用 nut 对象创建的坚果。 init 和 destroy 方法都是私有的,所以我在另一个配置中创建了一个扩展,以便创建一个模拟并能够用 Mockito 验证它。通过这种方式,我可以隐藏私有方法并为此测试生成公共方法。但是我认为在这种情况下对您来说有趣的是,在我的 @Configuration 中为 @Test 使用 @PreDestroy 注释,然后我可以测试 destroy 方法,因为在那时,所有的 destroy 方法都已被调用。这是我的代码的副本,只是为了澄清这一点:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {NutsConfiguration.class, NutsMethodsConfigurationTest.NutsTestConfiguration.class})
class NutsMethodsConfigurationTest {

    @Autowired
    public Nut almond;

    @MockBean
    public static NutExtended nutExtended;

    @Autowired
    public ApplicationContext applicationContext;

    @Test
    void almond() {
        ConsolerizerComposer.outSpace()
                .orange(almond)
                .orange(nutExtended)
                .reset();

        verify(nutExtended, times(1)).initiate();
    }

    @Configuration
    public static class NutsTestConfiguration {

        @Bean
        @Primary
        @Qualifier("nut")
        public NutExtended nut() {
            return new NutExtended();
        }

        @PreDestroy
        public void check() {
            verify(nutExtended, times(1)).goToCake();
        }
    }

    @Configuration
    public static class NutExtended extends Nut {

        public void goToCake() {
            BROWN.printGenericLn("Going to cake...");
        }


        public void initiate() {
            ORANGE.printGenericLn("Creating %s", toString());
        }
    }
}

我希望这会有所帮助?!