是否可以通过创建一个包含用于测试的模拟版本的@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());
}
}
答案 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。
为此,您可以参考以下问题:
答案 2 :(得分:0)
注释@EnableFeignClients
将为默认标记为@FeignClient
的接口创建主bean。对于每个接口都禁用此功能可能会产生副作用,例如使用后备bean时。
为了首先防止创建Feign bean,只需将此注释移到配置类中即可进行测试。
@Configuration
@Profile("!test")
@EnableFeignClients
public class FeignEnable {
}
然后用@ActiveProfiles("test")
注释测试类。