当有2个相同类型时如何@MockBean?

kan*_*ane 2 java spring dependency-injection mockito spring-boot

将尝试提供简化的示例(希望我不会在某个地方搞砸)

假设我有 2 个相同类型的 @Bean,但其中一个带有注释

@Configuration
public class FooProvider {

  @Bean
  public Foo foo1() {...}

  @Bean
  @SpecialFoo
  public Foo foo2() {...}

}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface SpecialFoo {}
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,Spring 似乎可以接受一个带注释的 bean 和一个未注释的 bean。该注解是@Qualifier

@Configuration
public class BarProvider {

  @Bean
  public Bar bar1(Foo foo1) {...}

  @Bean
  public Bar bar2(@SpecialFoo Foo foo2) {...}
}
Run Code Online (Sandbox Code Playgroud)

所有这些都有效。程序加载完毕,Spring 并没有抱怨。

但当我尝试测试它时,问题就出现了。

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureWebTestClient
public class MyTest {

  @MockBean
  Foo foo1;

  @MockBean @SpecialFoo
  Foo foo2;

}
Run Code Online (Sandbox Code Playgroud)

此时,我收到类似的错误

没有可用的“Foo”类型的合格 bean:预期有单个匹配 bean,但发现了 2 个:foo1、foo2

我究竟做错了什么?

特别要求:我不想foo1也注释或添加,@Qualifier因为它有很多我需要更改的地方。我宁愿默认 bean 是未注释的 bean。

kan*_*ane 5

这就是我发现的作品

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureWebTestClient
public class MyTest {

  @MockBean(name = "foo1")
  Foo foo1;

  @MockBean @SpecialFoo
  Foo foo2;

}
Run Code Online (Sandbox Code Playgroud)

我需要告诉 Spring 我用这个模拟替换了哪个 Foo @Bean,方法是给 Spring 指定要替换的 bean 的名称。如果MockBean有一个@Qualifier@SpecialFooQualifier注释,那么它不需要这个命名。所以只有未注释的 bean 才需要这个。

为了回答我在评论中的问题,这两个似乎是等效的:

@MockBean(name = "foo1")
Run Code Online (Sandbox Code Playgroud)

@MockBean @Qualifier("foo1")
Run Code Online (Sandbox Code Playgroud)

希望这对其他人有帮助