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

How to @MockBean when there are 2 of the same type?

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

假设我有 2 个相同类型的 @Beans,但其中一个被注释了

@Configuration
public class FooProvider {

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

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

}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface SpecialFoo {}

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

@Configuration
public class BarProvider {

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

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

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

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

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

  @MockBean
  Foo foo1;

  @MockBean @SpecialFoo
  Foo foo2;

}

此时,我收到类似

的错误

No qualifying bean of type 'Foo' available: expected single matching bean but found 2: foo1, foo2

我做错了什么?

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

尝试添加:

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

像这样

@Configuration
public class FooProvider {

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

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

}

...

@Autowire
@Qualifier("foo1")
Foo foo1;

@Autowire
@Qualifier("foo2")
Foo foo2;

这是我发现的作品

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

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

  @MockBean @SpecialFoo
  Foo foo2;

}

我需要告诉 Spring 我要用这个 mock 替换哪个 Foo @Bean,方法是给它提供要替换的 bean 的名称。如果 MockBean 具有 @Qualifier@SpecialFoo 限定符注释,则它不需要此命名。所以只有未注释的 bean 需要这个。

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

@MockBean(name = "foo1")

@MockBean @Qualifier("foo1")

希望这对其他人有帮助