使用Zuul过滤器的Spring Boot测试没有获取bean

时间:2016-07-27 20:45:22

标签: spring-cloud spring-test netflix-zuul

我正在使用@SpringBootTest与Zuul一起运行集成级别测试。不幸的是,我遇到了ApplicationContext刷新的问题。正在创建我的RouteLocator的多个实例,并且不会始终使用当前实例。我实现的RouteLocator也实现了RefreshableRouteLocator。我创建了一个非常简单的静态字段,每次创建实例时都会增加1。

private static int id = 0;
private int instanceId = id++;

测试利用WireMock来模拟从Zuul路由调用的后端服务。 WireMock配置为使用随机端口,因此我使用@Before和@After方法为每个测试修改RouteLocator中的路由。

@Autowired
protected LiveMigrationRouteLocator liveMigrationRouteLocator;

@Rule
public WireMockRule serviceA = new WireMockRule(Options.DYNAMIC_PORT);

@Rule
public WireMockRule serviceB = new WireMockRule(Options.DYNAMIC_PORT);

@Before
public void before() {
    LiveMigrationProperties routingProperties = liveMigrationRouteLocator.getRoutingProperties();
    for (LiveMigrationRoute route : routingProperties.getRoutes().values()) {
        route.setPrimaryUrl(route.getPrimaryUrl().replace("serviceA", "localhost:" + serviceA.port())
                .replace("serviceB", "localhost:" + serviceB.port()));
        route.setSecondaryUrl(route.getSecondaryUrl().replace("serviceA", "localhost:" + serviceA.port())
                .replace("serviceB", "localhost:" + serviceB.port()));
    }
    liveMigrationRouteLocator.setRoutingProperties(routingProperties);
    liveMigrationRouteLocator.refresh();

    serviceA.stubFor(get(urlPathMatching("/test-path/.*")).willReturn(aResponse()
            .withHeader("Content-Type", "application/json").withStatus(200).withBody("serviceA:test-path")));
    serviceB.stubFor(get(urlPathMatching("/test-path/.*")).willReturn(aResponse()
            .withHeader("Content-Type", "application/json").withStatus(200).withBody("serviceB:test-path")));
}

@After
public void after() {
    LiveMigrationProperties routingProperties = liveMigrationRouteLocator.getRoutingProperties();
    for (LiveMigrationRoute route : routingProperties.getRoutes().values()) {
        route.setPrimaryUrl(route.getPrimaryUrl().replace("localhost:" + serviceA.port(), "serviceA")
                .replace("localhost:" + serviceB.port(), "serviceB"));
        route.setSecondaryUrl(route.getSecondaryUrl().replace("localhost:" + serviceA.port(), "serviceA")
                .replace("localhost:" + serviceB.port(), "serviceB"));
    }
    liveMigrationRouteLocator.setRoutingProperties(routingProperties);
    liveMigrationRouteLocator.refresh();
}

我有多个测试类扩展了具有上述实现的基类。每个测试类都有以下注释:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@EnableConfigurationProperties(LiveMigrationProperties.class)
public class RoutingTests extends LiveMigrationWireMockTests {

运行测试时,我会调试日志记录,以便查看问题。日志位于http://pastebin.com/preMTZ22。如果你寻找"刷新路线[#]"其中#是正在使用的RouteLocator的实例。第一个测试通过正常,您可以看到它正在使用实例#0。然后运行下一个测试类并刷新ApplicationContext,以便创建一个新实例。你可以看到"刷新路线[1]"与"获得匹配路线[1]:..."对于从SimpleHostRoutingFilter查找的每个路由。

现在问题出现在下一个测试类运行时。 ApplicationContext再次刷新,因此"刷新路由[2]"出现。当SimpleHostRoutingFilter调用RouteLocator时,您可以看到"获取匹配路由[1]的日志:..."。这应该是"获得匹配路线[2]:......"。因此,SimpleHostRoutingFilter失败,因为它试图调用http://serviceA而不是WireMock的动态端口。

我试图在一个简单的测试中重新创建它,但我似乎无法重现它。简单的测试确实显示了正在创建的多个实例,但是当进行测试时,只有实例#0是与之交互的实例。 http://pastebin.com/9jiCRmRE

https://github.com/ShawnTuatara/stack-overflow-spring-boot-test-zuul-autowired-instance

0 个答案:

没有答案