是否可以通过创建包含用于测试的模拟版本的@Configuration
bean来覆盖通过@FeignClient
注释创建的bean?
我已经尝试过它,但是看来@FeignClient
bean是最后(或我认为(创建的,因为在我的测试中,我总是会注入真实版本,而不是嘲笑的版本。在同一配置文件中,我创建了另一个没有任何注释的bean(除了@Component
外(,仅使用真实的名称就以相同的方式模拟了相同的方式。
我已经尝试使用@MockBean
嘲笑它并且可以使用它,但是该项目上面有一些怪癖,这使得创建另一个春季上下文打破了测试。
谢谢。
编辑。实际上,我只是进行了调试测试,并意识到,如果我使用与Feign Client相同的名称,则调试器甚至不会在@Configuration
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());
}
}
您的问题是由feignclient bean定义为primary
的事实引起的,就像用@Primary
宣布Bean一样。因此,它比其他普通豆具有优先级。从Dalston版本中包括的Spring-Cloud-Netflix 1.3.0,您可以关闭此主配置如下。
@FeignClient(name = "fooService", primary = false)
public interface FooService {
}
如果您像上面的代码更改代码,则将模拟的Bean注射到您的测试中。
您需要小心的一件事是,当您使用后式bean作为feignclient时,使用primary
选项。如果您有后备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;
}
}
注释@EnableFeignClients
将为用@FeignClient
标记的接口创建主bean。为每个接口禁用此功能可能会产生副作用,例如有后备豆。
为了防止首先创建假豆的创建,只需将此注释移至用于测试的配置类。
@Configuration
@Profile("!test")
@EnableFeignClients
public class FeignEnable {
}
然后用@ActiveProfiles("test")
注释您的测试类。
如果您可以共享测试类,那将是很棒的。
我了解您的问题是您需要在测试中覆盖豆子。
为此,您可以参考以下问题:
在单元测试中覆盖自动豆
它是一个错误,已固定在2.2.3假词中。