Jua*_*ega 5 java spring unit-testing mockito feign
是否可以通过@FeignClient创建@Configuration包含模拟版本的 bean 进行测试来覆盖通过注释创建的bean?
我已经尝试过了,但似乎@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());
}
}
Run Code Online (Sandbox Code Playgroud)
您的问题是由于 FeignClient beans 的定义就像primary使用@Primary. 所以它比其他普通豆子有优先权。从 Dalston 版本中包含的 spring-cloud-netflix 1.3.0 开始,您可以像下面这样关闭此主要配置。
@FeignClient(name = "fooService", primary = false)
public interface FooService {
}
Run Code Online (Sandbox Code Playgroud)
如果您像上面那样更改代码,模拟 bean 将被注入到您的测试中。
您需要注意的一件事是,primary当您为 FeignClient 使用后备 bean 时,会使用该选项。如果您有后备 bean,则可能需要使用限定符指定 FeignClient bean,以通过后备 bean 获取 FeignClient 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;
}
}
Run Code Online (Sandbox Code Playgroud)