Spring boot 在基于Netty的应用程序中进行单元测试后,SpringApplication未关闭

Spring boot 在基于Netty的应用程序中进行单元测试后,SpringApplication未关闭,spring-boot,netty,spring-boot-test,Spring Boot,Netty,Spring Boot Test,我有一个很烦人的服务,就是“春天化”。该服务运行良好,可以处理请求/响应 我没有添加单元测试/集成测试。我看到springcontext并没有在测试后关闭。即netty服务器在测试完成后运行。我可以远程登录到该端口,并查看它是否仍然连接到该端口 这是我的SpringBootApp文件 @SpringBootApplication public class NettyService { //Autowired all the required fields //I made t

我有一个很烦人的服务,就是“春天化”。该服务运行良好,可以处理请求/响应

我没有添加单元测试/集成测试。我看到springcontext并没有在测试后关闭。即netty服务器在测试完成后运行。我可以远程登录到该端口,并查看它是否仍然连接到该端口

这是我的SpringBootApp文件

@SpringBootApplication
public class NettyService {

    //Autowired all the required fields

    //I made this static so I can access from integration tests to shut it down. I shouldn't need
    //this since after each test jvm should be shut-down.
    static ChannelFuture serverChannelFuture;

    public static void main( String[] args ) {
        SpringApplication.run(NettyService.class, args);

    }

    @PostConstruct
    public void start() throws InterruptedException {
        serverChannelFuture = bootstrap.bind(tcpSocketAddress).sync();
    }

    @PreDestroy
    public void stop() throws InterruptedException {
        serverChannelFuture.channel().closeFuture().sync();
    }

}
测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes=NettyService.class)
public class AppTest
{

    @After
    public void cleanUp() throws Exception {
        //NettyService.serverChannelFuture.channel().closeFuture().sync();
    }


    @Test
    public void contextLoad1() throws Exception
    {
        assertTrue( true );
    }

    @Test
    public void contextLoad2() throws Exception
    {
        assertTrue( true );
    }
第一次测试时,它通过得很好。但第二次测试失败,出现“地址正在使用”错误。 第一次测试完成后,Netty没有拆掉。我希望spring上下文在测试结束或至少jvm退出时关闭


注意,我已经注释掉了cleanUp()方法中的行。如果我取消注释,即使第一个测试也不会运行。它只是永远挂着。

你不正确地关闭了Netty

这只是等待服务器通道关闭,但它从未请求它实际关闭,这将永远阻塞

不要调用
.closeFuture()
(将来的事件),而是调用
.close()
(立即关闭它)


如果您还使用新的
NioEventLoopGoup
实例创建线程池,请确保在关闭通道后调用其关闭功能来终止线程池。

您正在错误地关闭Netty

这只是等待服务器通道关闭,但它从未请求它实际关闭,这将永远阻塞

不要调用
.closeFuture()
(将来的事件),而是调用
.close()
(立即关闭它)


如果还使用
NioEventLoopGoup
的新实例创建线程池,请确保在关闭通道后调用其shutdown函数来终止该操作。

除非您使用
@DirtiesContext
,否则它不会在测试之间重新启动,否则它将启动一次并重新使用。应用程序不应该在测试结束时关闭吗?我运行了一个测试,在测试通过后,它仍然永远挂在那里,我可以在端口上ping服务器如果您运行多个测试类(一个
@test
方法是测试,而不是在我的测试定义中定义的类),它将保持启动状态,直到最后一个类的最后一个测试方法运行为止。如果您在这里只运行这个类,那么有两个测试,在两个方法都执行之后,它应该关闭。如果这种情况没有发生,那就与您的设置有关,这可能是因为您正在管理自己的Netty,而不是让Spring Boot控制生命周期。我让Spring Boot管理Netty。由于它没有关闭,我尝试在cleanUp()中强制关闭,这也没有帮助。您没有让Spring Boot管理Netty,因为您的Spring Boot应用程序中有
@PreDestroy
@PostConstruct
。这意味着您实际上是在控制Netty实例,而不是Spring启动。除非您使用
@DirtiesContext
,否则它不会在测试之间重新启动,但它会启动一次并重新使用。应用程序不应该在测试结束时关闭吗?我运行了一个测试,在测试通过后,它仍然永远挂在那里,我可以在端口上ping服务器如果您运行多个测试类(一个
@test
方法是测试,而不是在我的测试定义中定义的类),它将保持启动状态,直到最后一个类的最后一个测试方法运行为止。如果您在这里只运行这个类,那么有两个测试,在两个方法都执行之后,它应该关闭。如果这种情况没有发生,那就与您的设置有关,这可能是因为您正在管理自己的Netty,而不是让Spring Boot控制生命周期。我让Spring Boot管理Netty。由于它没有关闭,我尝试在cleanUp()中强制关闭,这也没有帮助。您没有让Spring Boot管理Netty,因为您的Spring Boot应用程序中有
@PreDestroy
@PostConstruct
。这意味着您实际上是在控制Netty实例,而不是Spring Boot。
@PreDestroy
public void stop() throws InterruptedException {
    serverChannelFuture.channel().closeFuture().sync();
}
@PreDestroy
public void stop() throws InterruptedException {
    serverChannelFuture.channel().close().sync();
}