首页 > 解决方案 > ContextRefreshedEvent 在 Spring 集成测试中过早触发

问题描述

我想测试一个Example处理 aContextRefreshedEvent并在处理程序方法中连接到服务器的类:

public class Example {

    @EventListener
    public void onApplicationEvent(ContextRefreshedEvent event) {
        startWebSocketConnection();
    }

    // ...
}

但是在集成测试中,应用程序上下文是在 Web 套接字服务器启动并运行之前构建的,所以我得到一个异常,说连接失败(java.net.ConnectException: Connection refused: no further information在这种情况下)。

测试看起来像这样:

@ExtendWith(SpringExtension.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest
public class WebSocketDataSourceTest {

    @Autowired 
    private Example example;

    @Autowired
    private WebSocketServer server; // created too late

    // ...
}

是否有可能以某种方式抑制ContextRefreshedEvent或推迟应用程序上下文的创建,以便 Web 套接字服务器可以在之前启动?还是有其他解决方案?

标签: javaspringspring-bootevent-handlingspring-boot-test

解决方案


似乎没有办法抑制 Spring 框架触发的事件或推迟应用程序上下文的创建。所以我想出了以下解决方法:

import org.springframework.core.env.Environment;

public class Example {

    private boolean skipNextEvent;

    @Autowired
    public Example(Environment environment) {
        skipNextEvent = environment.acceptsProfiles("test");
    }

    @EventListener
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (skipNextEvent) {
            skipNextEvent = false;
            return;
        }
        startWebSocketConnection();
    }

    // ...
}

测试手动触发事件处理程序。

@ExtendWith(SpringExtension.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest
@ActiveProfiles("test") // set profile "test"
public class WebSocketDataSourceTest {

    @Autowired 
    private Example example;

    @Autowired
    private WebSocketServer server;

    @Test
    public void shouldWork() {
        // ...
        example.onApplicationEvent(null); // trigger manually
        // ...
    }
}

推荐阅读