1

我想对使用 Netty 构建的套接字服务器进行一些单元测试。

Socket Server 有以下简单的代码:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class SocketServer implements Runnable {

    private int port;

    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;

    private ChannelFuture channelFuture;
    private ServerBootstrap bootstrap;

    public SocketServer(int port) {
        this.port = port;
        this.bossGroup = new NioEventLoopGroup();
        this.workerGroup = new NioEventLoopGroup();
    }

    public int getPort() {
        return port;
    }

    @Override
    public void run() {
        try {
            bootstrap = new ServerBootstrap();
            bootstrap
                    .group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch)
                                throws Exception {
                            ch.pipeline()
                                    .addLast(new ReceiveMessageServerHandler())
                                    .addLast(new ParseMessageServerHandler());
                        }
                    }).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);

            // Bind and start to accept incoming connections.
            channelFuture = bootstrap.bind(port).sync();

            // Wait until the server socket is closed
            channelFuture.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();

        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public void shutdown() throws InterruptedException {
        channelFuture.channel().close();
    }

}

在 MessageHandlers 上,我首先会收到由 '\n' 分隔的文本消息。我非常需要一个 telnet 客户端。

我想测试我是否可以向服务器发送不同的消息,并且我是否会在某个时间范围内收到某些预期的响应。

我尝试使用 Citrus Framework,但无法获得任何结果,因为它没有提供适当的纯文本协议(我尝试过 Rest、Soap 等,但它们对我没有好处)。我在 Citrus Reference 2.4 中找不到答案。

Citrus 2.4 参考 - HTML 版本

4

2 回答 2

2

您还可以为此使用 Citrus Apache Camel 集成。您需要 citrus-camel 模块和 camel- netty ( http://camel.apache.org/netty.html ) 或 camel-netty4 ( http://camel.apache.org/netty4.html ) 依赖项。然后就可以直接使用 Camel Netty 组件发送消息了:

@Test
@CitrusTest
public void sendNettyMessageTest() {
    status(Status.DRAFT);
    //sends data to server
    send("camel:netty4:tcp://localhost:9123").payload("Message 1");
    send("camel:netty4:tcp://localhost:9123").payload("Message 2");
}

这是利用 Citrus 中的动态端点,其中端点配置是在测试运行时创建的。所以这里几乎不需要额外的配置!

于 2016-03-03T10:36:31.293 回答
1

我能够在发布问题之前解决问题(我昨天写了问题,但直到今天才发布......我找到了答案)。

所以我终于可以用 Citrus Framework 和 Spring Integration 解决这个问题。

在与同事一起阅读本文后,我能够使用 Spring Integration TCP 适配器作为 Citrus 端点的通道(来自 java.nio 的 SocketChannel)。

Spring 集成参考 - IP

在这里你可能会看到我使用的 citrus-context.xml 配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:citrus="http://www.citrusframework.org/schema/config"
    xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
        http://www.citrusframework.org/schema/config http://www.citrusframework.org/schema/config/citrus-config.xsd
        http://www.springframework.org/schema/integration  http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/integration/ip  http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">

    <citrus:channel-endpoint id="citrusServiceEndpoint"
        channel-name="input" />

    <int-ip:tcp-connection-factory id="client"
        type="client" host="localhost" port="9123" single-use="true"
        so-timeout="10000" using-nio="true" />

    <int:channel id="input" />

    <int-ip:tcp-outbound-channel-adapter
        id="outboundClient" channel="input" connection-factory="client" />

</beans>

在我的柑橘测试中,我能够根据需要发送消息:

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import com.consol.citrus.TestCaseMetaInfo.Status;
import com.consol.citrus.annotations.CitrusTest;
import com.consol.citrus.dsl.junit.JUnit4CitrusTestDesigner;

public class MyFirstTest extends JUnit4CitrusTestDesigner {

    private static final int PORT = 9123;
    private static SocketServer socketServer;
    private static Thread socketThread;

    @BeforeClass
    public static void setUp() throws Exception {
        socketServer = new SocketServer(PORT);
        socketThread = new Thread(socketServer);
        socketThread.start();
    }

    @AfterClass
    public static void tearDown() throws Exception {
        socketServer.shutdown();
        socketThread.join();
    }

    @Test
    @CitrusTest(name = "sendSpringIntegrationMessageTest")
    public void sendSpringIntegrationMessageTest() {
        status(Status.DRAFT);
        send("citrusServiceEndpoint").payload("Message 1");
        send("citrusServiceEndpoint").payload("Message 2");
    }

}

我希望这可以帮助任何可能遇到与我相同问题的人。

于 2015-12-30T18:34:33.020 回答