mockito 使用@Configuration bean测试@FeignClient

ha5z0ras  于 9个月前  发布在  其他
关注(0)|答案(4)|浏览(115)

有没有可能通过创建一个@Configuration bean来覆盖通过@FeignClient注解创建的bean,该bean包含一个用于测试的模拟版本?
我已经试过了,但似乎@FeignClient bean是最后创建的(或者我认为是这样),因为在我的测试中,我总是注入真实的版本,而不是模拟的版本。在同一个配置文件中,我创建了另一个没有任何注解的bean(除了@Component),通过使用真实的bean的名称以同样的方式模仿它,它工作得很好。
我试过使用@MockBean来模拟它,它可以工作,但是项目有一些怪癖,使得另一个Spring上下文的创建破坏了测试。
谢谢.
实际上,我刚刚调试了测试,并意识到,如果我使用与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());
  }
}
6ljaweal

6ljaweal1#

你的问题是由FeignClient bean被定义为primary这一事实引起的,就像用@Primary声明bean一样。所以它比其他正常的豆子有优先权。从Dalston版本中包含的spring-cloud-network1.3.0中,您可以关闭此主配置,如下所示。

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

如果你像上面那样修改你的代码,Mocked bean将被注入到你的测试中。
需要注意的一件事是,当您为FeignClient使用fallback bean时,会使用primary选项。如果你有fallback bean,你可能需要指定FeignClient bean with qualifer来获取FeignClient bean over fallback bean。
我认为另一种注入mocked 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;
    }
}
l7wslrjt

l7wslrjt2#

默认情况下,注解@EnableFeignClients将为标记为@FeignClient的接口创建主bean。对每个接口禁用此功能可能会产生副作用,例如当存在回退bean时。
为了防止在第一时间创建Feign bean,只需将此注解移动到测试禁用的配置类。

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

}

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

mzillmmw

mzillmmw3#

如果你能分享你的测试类就太好了。
正如我所理解的,你的问题是你需要在测试中重写一个bean。
要做到这一点,您可以参考以下问题:
Overriding an Autowired Bean in Unit Tests

jljoyd4f

jljoyd4f4#

这是一个bug,已在2.2.3 Feign中修复。

相关问题