19

我的 Spring 上下文中有几个具有状态的 bean,因此我想在单元测试之前/之后重置该状态。

我的想法是向一个助手类添加一个方法,该类只遍历 Spring 上下文中的所有 bean,检查使用@Beforeor注释的方法@After并调用它们。

如何从 中获取实例化bean的列表ApplicationContext

注意:简单地遍历所有定义的 bean 的解决方案是没有用的,因为我有很多惰性 bean,其中一些不能实例化,因为某些测试会失败(即我有一个需要 ajava.sql.DataSource但测试工作的 bean,因为它们没有'不需要那个豆子)。

4

6 回答 6

22

例如:

 public static List<Object> getInstantiatedSigletons(ApplicationContext ctx) {
            List<Object> singletons = new ArrayList<Object>();

            String[] all = ctx.getBeanDefinitionNames();

            ConfigurableListableBeanFactory clbf = ((AbstractApplicationContext) ctx).getBeanFactory();
            for (String name : all) {
                Object s = clbf.getSingleton(name);
                if (s != null)
                    singletons.add(s);
            }

            return singletons;

    }
于 2013-02-12T14:07:51.777 回答
3

我不确定这是否会对您有所帮助。

您需要创建自己的注释,例如。我的注释。并将该注释放在您想要获取的类上。然后使用以下代码,您可能会得到实例化的 bean。

ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnot.class));
for (BeanDefinition beanDefinition : scanner.findCandidateComponents("com.xxx.yyy")){
    System.out.println(beanDefinition.getBeanClassName());
}

通过这种方式,您可以获得具有自定义注释的所有 bean。

于 2013-02-12T12:24:13.793 回答
3

我不得不稍微改进一下

@Resource
AbstractApplicationContext context;

@After
public void cleanup() {
    resetAllMocks();
}

private void resetAllMocks() {
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    for (String name : context.getBeanDefinitionNames()) {
        Object bean = beanFactory.getSingleton(name);
        if (Mockito.mockingDetails(bean).isMock()) {
            Mockito.reset(bean);
        }
    }
}
于 2015-10-22T16:02:37.117 回答
3

applicationContext.getBeanDefinitionNames()不显示在没有BeanDefinition 实例的情况下注册的 bean 。

package io.velu.core;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class Core {

public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Core.class);
    String[] singletonNames = context.getDefaultListableBeanFactory().getSingletonNames();
    for (String singleton : singletonNames) {
        System.out.println(singleton);
    }       
}

}


控制台输出

environment
systemProperties
systemEnvironment
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
messageSource
applicationEventMulticaster
lifecycleProcessor

正如您在输出中看到的,环境、systemProperties、systemEnvironment bean不会使用context.getBeanDefinitionNames()方法显示。

弹簧靴

对于 Spring Boot Web 应用程序,可以使用以下端点列出所有 bean。

@RestController
@RequestMapping("/list")
class ExportController {

@Autowired
private ApplicationContext applicationContext;

@GetMapping("/beans")
@ResponseStatus(value = HttpStatus.OK)
String[] registeredBeans() {
    return printBeans();
}

private String[] printBeans() {
    AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
    if (autowireCapableBeanFactory instanceof SingletonBeanRegistry) {
        String[] singletonNames = ((SingletonBeanRegistry) autowireCapableBeanFactory).getSingletonNames();
        for (String singleton : singletonNames) {
            System.out.println(singleton);
        }
        return singletonNames;
    }
    return null;
}

}


[“autoConfigurationReport”、“springApplicationArguments”、“springBootBanner”、“springBootLoggingSystem”、“环境”、“systemProperties”、“systemEnvironment”、“org.springframework.context.annotation.internalConfigurationAnnotationProcessor”、“org.springframework.boot.autoconfigure. internalCachingMetadataReaderFactory”、“org.springframework.boot.autoconfigure.condition.BeanTypeRegistry”、“org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry”、“propertySourcesPlaceholderConfigurer”、“org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.store” , "preserveErrorControllerTargetClassPostProcessor”、“org.springframework.context.annotation.internalAutowiredAnnotationProcessor”、“org.springframework.context.annotation.internalRequiredAnnotationProcessor”、“org.springframework.context.annotation.internalCommonAnnotationProcessor”、“org.springframework.boot.context.properties. ConfigurationPropertiesBindingPostProcessor”、“org.springframework.scheduling.annotation.ProxyAsyncConfiguration”、“org.springframework.context.annotation.internalAsyncAnnotationProcessor”、“methodValidationPostProcessor”、“embeddedServletContainerCustomizerBeanPostProcessor”、“errorPageRegistrarBeanPostProcessor”、“messageSource”、“applicationEventMulticaster”、“org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration$EmbeddedTomcat”、“tomcatEmbeddedServletContainerFactory”、“org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration$TomcatWebSocketConfiguration”、“websocketContainerCustomizer”、“spring.http.encoding- org.springframework.boot.autoconfigure.web.HttpEncodingProperties”、“org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration”、“localeCharsetMappingsCustomizer”、“org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration”、“serverProperties”、“重复服务器属性检测器”、“spring.resources-org.springframework.boot.autoconfigure.web.ResourceProperties”、“org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration”、“conventionErrorViewResolver”、“org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration”、“errorPageCustomizer”、“servletContext”、“ contextParameters”、“contextAttributes”、“spring.mvc-org.springframework.boot.autoconfigure.web.WebMvcProperties”、“spring.http.multipart-org.springframework.boot.autoconfigure.web.MultipartProperties”、“org.springframework. boot.autoconfigure.web.MultipartAutoConfiguration”、“multipartConfigElement”、“org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration”、“org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration$DispatcherServletConfiguration”、“dispatcherServlet”、“dispatcherServletRegistration”、“requestContextFilter”、“org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration”、“hiddenHttpMethodFilter” 、“httpPutFormContentFilter”、“characterEncodingFilter”、“org.springframework.context.event.internalEventListenerProcessor”、“org.springframework.context.event.internalEventListenerFactory”、“reportGeneratorApplication”、“exportController”、“exportService”、“org.springframework.开机。autoconfigure.AutoConfigurationPackages”、“org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration”、“org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration”、“spring.jackson-org.springframework.boot.autoconfigure.jackson. JacksonProperties”、“standardJacksonObjectMapperBuilderCustomizer”、“org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration”、“org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration”、“jsonComponentModule”、“jacksonObjectMapperBuilder”、“org.springframework.引导自动配置杰克逊。JacksonAutoConfiguration$JacksonObjectMapperConfiguration”、“jacksonObjectMapper”、“org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration”、“org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration”、“org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration” , “org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration”, “defaultValidator”, “org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration”, “error”, “beanNameViewResolver”, “errorAttributes”, “basicErrorController” , "org.springframework.boot.autoconfigure.web。WebMvcAutoConfiguration$EnableWebMvcConfiguration”、“org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter”、“mvcContentNegotiationManager”、“org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration”、“stringHttpMessageConverter”、“org.springframework. boot.autoconfigure.web.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration”、“mappingJackson2HttpMessageConverter”、“org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration”、“messageConverters”、“mvcConversionService”、“mvcValidator”、“requestMappingHandlerAdapter”、“mvcResourceUrlProvider”、“requestMappingHandlerMapping”、“mvcPathMatcher”、“mvcUrlPathHelper”、“viewControllerHandlerMapping”、“beanNameHandlerMapping”、“resourceHandlerMapping”、“defaultServletHandlerMapping”、“mvcUriComponentsContributor”、“httpRequestHandlerAdapter”、“simpleControllerHandlerAdapter”、“handlerExceptionResolver” ,“mvcViewResolver”,“org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter$FaviconConfiguration”,“faviconRequestHandler”,“faviconHandlerMapping”,“defaultViewResolver”,“viewResolver”、“welcomePageHandlerMapping”、“org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration”、“objectNamingStrategy”、“mbeanServer”、“mbeanExporter”、“org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration”、“springApplicationAdminRegistrar” ,“org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration”,“org.springframework.boot.autoconfigure.web.JacksonHttpMessageConvertersConfiguration”,“spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties”,“org. springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration”、“multipartResolver”、“org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration$RestTemplateConfiguration”、“restTemplateBuilder”、“org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration”、“spring.devtools-org.springframework.boot.devtools.autoconfigure.DevToolsProperties”、“ org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfiguration$RestartConfiguration”、“fileSystemWatcherFactory”、“classPathRestartStrategy”、“classPathFileSystemWatcher”、“hateoasObjenesisCacheDisabler”、“org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfiguration$LiveReloadConfiguration$LiveReloadServerConfiguration”、“ org.springframework.boot.devtools.autoconfigure。LocalDevToolsAutoConfiguration$LiveReloadConfiguration", "optionalLiveReloadServer", "org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfiguration", "lifecycleProcessor"]

于 2019-02-26T08:32:10.270 回答
0

我创建了一个要点 ApplicationContextAwareTestBase

这个助手类做了两件事:

  1. 它将所有内部字段设置为空。这允许 Java 释放不再使用的内存。不过,它对 Spring 的用处不大(Spring 上下文仍然保留对所有 bean 的引用)。

  2. 它尝试@After在上下文中的所有 bean 中找到所有带有注释的方法,并在测试后调用它们。

这样,您可以轻松地重置单例/模拟的状态,而无需销毁/刷新上下文。

示例:您有一个模拟 DAO:

public void MockDao implements IDao {

    private Map<Long, Foo> database = Maps.newHashMap();

    @Override
    public Foo byId( Long id ) { return database.get( id ) );

    @Override
    public void save( Foo foo ) { database.put( foo.getId(), foo ); }

    @After
    public void reset() { database.clear(); }
}

注释将确保reset()在每个单元测试后调用以清理内部状态。

于 2013-02-12T15:16:08.590 回答
0

使用以前的答案,我已将其更新为使用 Java 8 Streams API:

@Inject
private ApplicationContext applicationContext;

@Before
public void resetMocks() {
    ConfigurableListableBeanFactory beanFactory = ((AbstractApplicationContext) applicationContext).getBeanFactory();
    Stream.of(applicationContext.getBeanDefinitionNames())
            .map(n -> beanFactory.getSingleton(n))
            // My ConfigurableListableBeanFactory isn't compiled for 1.8 so can't use method reference. If yours is, you can say
            // .map(ConfigurableListableBeanFactory::getSingleton)
            .filter(b -> Mockito.mockingDetails(b).isMock())
            .forEach(Mockito::reset);
}
于 2016-09-25T19:42:02.753 回答