在不启用Bean覆盖的情况下在Spring Boot 2.1中连接测试

时间:2019-01-04 20:16:06

标签: spring-boot testing

我有使用命名bean的代码

@Bean
@Named("heimdall-uri-supplier")
public URISupplier heimdallEndpointSupplier(CredentialsClientConfig config, EnvInfo envInfo) {
    ....
}

@Named("vault-uri-supplier")
@Bean
public URISupplier vaultURISupplier(EnvInfo envInfo, CredentialsClientConfig config) {
   ....
}

它们被明确命名是因为我希望将特定的实现注入到不同的使用类中。这些类也使用@Named。

在测试中,在Spring Boot 2.1之前

@Bean
@Primary
@Named("heimdall-uri-supplier")
public URISupplier heimdallEndpointSupplier(CredentialsClientConfig config, EnvInfo envInfo) {
    return mock of some sort
}

@Named("vault-uri-supplier")
@Bean
@Primary
public URISupplier vaultURISupplier(EnvInfo envInfo, CredentialsClientConfig config) {
   return mock of some sort
}

做得很好。

现在,当然,Spring Boot 2.1会禁用覆盖。我知道我可以重新启用它,但是从理论上讲我不愿意这样做。

但是我的“常规”解决方法(做@Bean(name =“ testFoo”)在这里不起作用,因为使用类中的@Named注入器现在将失败。

有什么解决办法吗?

1 个答案:

答案 0 :(得分:0)

我设法做到了,但这确实很痛苦。我必须使用BeanDefinitionRegistryPostProcessor。设置GenericBeanDefinition很丑陋。在这里还不错,因为模拟是无参数的。如果必须将它们基于注入或设置构造函数args,则确实会涉及到很多事情。

/**
 * This class basically removes the existing bean definition and substitutes in the mocks.
 * Normally we don't need this - we just change the bean name. However because the
 * classes use an @Named qualifier, more heroic efforts are needed
 */
public static class OverridePostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(final BeanDefinitionRegistry registry) throws BeansException {
        if (registry.isBeanNameInUse("vault-uri-supplier")) {
            registry.removeBeanDefinition("vault-uri-supplier");
        }
        // Note: These are a bear to work with, but in theory you can build
        // them from scratch based on injected beans etc. Fortunately these
        // two examples just needed a no-args supplier
        GenericBeanDefinition g = new GenericBeanDefinition();
        g.setBeanClass(URISupplier.class);
        g.setInstanceSupplier(this::vaultURISupplier);
        registry.registerBeanDefinition("vault-uri-supplier", g);
        if (registry.isBeanNameInUse("taskRequestValidator")) {
            registry.removeBeanDefinition("taskRequestValidator");
        }
        g = new GenericBeanDefinition();
        g.setBeanClass(TaskRequestValidator.class);
        g.setInstanceSupplier(this::taskRequestValidator);
        registry.registerBeanDefinition("taskRequestValidator", g);


    }

    URISupplier vaultURISupplier() {
        return new com.opentable.credentials.client.internal.TestVaultConfiguration.MockSupplier();
    }
    TaskRequestValidator taskRequestValidator() {
        return (getTokenRequest, servicePolicy) -> ValidationResult.OK;
    }

    @Override
    public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException {
        /* No op */
    }
}