5

是否可以通过仅创建一个包含用于测试的模拟版本的bean 来覆盖通过@FeignClient注释创建的bean?@Configuration

我已经尝试过了,但似乎@FeignClientbean 是最后创建的(或者我认为),因为在我的测试中,我总是注入真实版本而不是模拟版本。在同一个配置文件中,我创建了另一个没有任何注释(除了@Component)的 bean,仅使用真实的名称以相同的方式模拟,并且它运行良好。

我尝试过使用@MockBean它来模拟它并且它可以工作,但是该项目有一些怪癖,这使得创建另一个 Spring 上下文会破坏测试。

谢谢。

编辑。实际上,我只是调试了测试并意识到,如果我使用与 Feign 客户端相同的名称,调试器甚至不会停止在@Configurationbean 中创建模拟版本。将名称更改为它可以工作的其他名称,但它只是使用新名称创建另一个相同类型的 bean。我在这里缺少任何配置吗?

编辑 2. 这是一个示例代码。执行这个我有BarService一个模拟版本,但FooService它是真实的。

@FeignClient(name = "fooService")
public interface FooService {
}

@Component
public class BarService {
}

@Configuration
public class ConfigClass {

  @Bean
  public FooService fooService() {
    return Mockito.mock(FooService.class);
  }

  @Bean
  public BarService barService() {
    return Mockito.mock(BarService.class);
  }

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@SpringBootTest
public class TestClass {

  @Autowired
  private FooService fooService;

  @Autowired
  private BarService barService;

  @Test
  public void test() {
    System.out.println(fooService.getClass());
  }
}
4

3 回答 3

5

您的问题是由于 FeignClient bean 被定义为primary像用@Primary. 所以它比其他普通的豆子有优先权。从 Dalston 版本中包含的 spring-cloud-netflix 1.3.0 中,您可以关闭此主要配置,如下所示。

@FeignClient(name = "fooService", primary = false)
public interface FooService {
}

如果您像上面那样更改代码,Mocked bean 将被注入到您的测试中。

您需要注意的一件事primary是当您为 FeignClient 使用后备 bean 时使用该选项。如果您有备用 bean,您可能需要使用限定符指定 FeignClient bean 以获取 FeignClient bean 而不是备用 bean。

我认为另一种注入模拟 bean 而不是 FeignClient bean 进行测试的方法是使用BeanPostProcessor类似下面的东西。

public static class MockProcessor implements BeanPostProcessor {
         : 
         :
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (/* distinguish your target bean */) 
            return Mockito.mock(FooService.class);
        return bean;
    }
}
于 2017-06-01T04:14:05.273 回答
2

注释将为默认@EnableFeignClients标记为的接口创建主 bean 。@FeignClient为每个接口禁用此功能可能会产生副作用,例如当有备用 bean 时。

为了首先防止创建 Feign bean,只需将此注释移动到对测试禁用的配置类。

@Configuration
@Profile("!test")
@EnableFeignClients
public class FeignEnable {

}

然后用注释你的测试类@ActiveProfiles("test")

于 2018-08-18T21:51:15.030 回答
1

如果您可以分享您的测试课程,那就太好了。

据我了解,您的问题是您需要在测试中覆盖一个 bean。

为此,您可以参考以下问题:

在单元测试中覆盖自动装配的 Bean

于 2017-05-30T15:23:55.513 回答