使用@Configuration bean覆盖@FeignClient进行测试

时间:2017-05-30 15:11:40

标签: java spring unit-testing mockito feign

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

我已经尝试过了,但似乎@FeignClient bean最后创建(或者我认为),因为在我的测试中我总是注入真实版本而不是模拟版本。在同一个配置文件中,我创建了另一个没有任何注释的bean(除@Component之外)通过使用真实的名称来嘲弄相同的方式,它完美地工作。

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

感谢。

EDIT。实际上,我只是调试了测试并意识到,如果我使用与Feign客户端相同的名称,调试器甚至不会在@Configuration bean中停止创建模拟版本。将名称更改为其他可用的名称,但它只是使用新名称创建另一个具有相同类型的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());
  }
}

3 个答案:

答案 0 :(得分:2)

你的问题是由于FeignClient bean被定义为primary这样的事实,就像声明一个带有@Primary的bean一样。所以它优先于其他正常的bean。 从Dalston版本中包含的spring-cloud-netflix 1.3.0开始,您可以关闭此主要配置,如下所示。

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

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

您需要注意的一件事是,当您为FeignClient使用fallback bean时,会使用primary选项。如果你有fallback bean,你可能需要用qualifer指定FeignClient bean来获得FebackClient bean而不是fallback 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;
    }
}

答案 1 :(得分:1)

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

据我所知,您的问题是您需要覆盖测试中的bean。

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

Overriding an Autowired Bean in Unit Tests

答案 2 :(得分:0)

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

为了首先防止创建Feign bean,只需将此注释移到配置类中即可进行测试。

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

}

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