WebFluxTest 注解默认不排除依赖于数据源的 Spring beans

问题描述 投票:0回答:1

我正在为 Spring Boot 应用程序设置一个模板 - 在最新版本上

3.2.4
。我面临的问题是测试用例。

我正在使用

@WebFluxTest
控制器 上运行测试用例,但不知何故它并没有跳过与数据库相关的自定义 Spring beans :/

这就是应用程序的配置方式(为简洁起见,跳过导入和构造函数):

@SpringBootApplication(scanBasePackages = { "tld.domain.controller", "tld.domain.service" })
public class Application {
  public static void main(final String... args) {
    SpringApplication.run(Application.class, args);
  }

  @EnableTransactionManagement
  @Configuration(proxyBeanMethods = false)
  @EnableJdbiRepositories(basePackages = "tld.domain.repository")
  public static class PersistenceConfig {
    @Bean
    public Jdbi jdbi(final DataSource dataSource) {
      return Jdbi.create(new SpringConnectionFactory(dataSource))
          .installPlugin(new SqlObjectPlugin());
    }
  }
}

控制器、服务和存储库类非常标准:

@RestController
public class TypeResource {
  final TypeService service;

  @GetMapping(path = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
  public ResponseEntity<Type> getByID(@PathVariable("id") final String id) {
    return ResponseEntity.of(service.getByID(id));
  }
}
@Service
public class TypeService {
  final TypeRepository repository;

  public Optional<Type> getByID(final String id) {
    return repository.getByID(id);
  }
}

最后,示例控制器的测试用例如下所示:

@ActiveProfiles("test")
@WebFluxTest(controllers = TypeResource.class)
final class TypeResourceTest {
  @Autowired
  private WebTestClient webClient;

  @MockBean
  private TypeService service;

  ...
}

尽管使用了

@WebFluxTest
,测试用例并没有跳过与数据库相关的自定义 Spring bean 配置,从而导致测试环境中出现意外行为。

这些是堆栈跟踪的相关部分:

TypeResourceTest > getByID() FAILED
    java.lang.IllegalStateException: Failed to load ApplicationContext for [ReactiveWebMergedContextConfiguration@4afd65fd testClass = tld.domain.resource.TypeResourceTest, locations = [], classes = [tld.domain.Application], contextInitializerClasses = [], activeProfiles = ["test"], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.testcontainers.service.connection.ServiceConnectionContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@30f4b1a6, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@14ff57cc, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@e5029446, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@2fb69ff6, [ImportsContextCustomizer@4b5ad306 key = [org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration, org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration, org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration, org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration, org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration, org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration, org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration, org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration, org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration, org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration, org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@d4602a, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@15515c51, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@be84b7c9, org.springframework.boot.test.context.SpringBootTestAnnotation@e0ed3db8], contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
        at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:180)
        ...
        Caused by:
        org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jdbi' defined in tld.domain.Application$PersistenceConfig: Unsatisfied dependency expressed through method 'jdbi' parameter 0: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
            at app//org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798)
            at app//org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542)
            ... 85 more
            Caused by:
            org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
                ... 109 more

任何有关如何解决此问题的见解或建议将不胜感激。

java spring-boot spring-webflux
1个回答
0
投票

@ConditionalOnBean(DataSource.class)
放在
PersistenceConfig
上解决了问题,因为它有效地确保仅当数据源可用或在应用程序上下文中配置时才加载
PersistenceConfig
中的 bean。

© www.soinside.com 2019 - 2024. All rights reserved.