ContextRefreshedEvent 在 Spring 集成测试中过早触发

ContextRefreshedEvent fired too early in Spring integration test

我想测试像 Example 这样的 class 处理 ContextRefreshedEvent 并在处理程序方法中连接到服务器:

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 套接字服务器可以提前启动?或者有其他解决方案吗?

似乎没有办法抑制 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
        // ...
    }
}