如何测试 Java EE7 Websocket
How to test a Java EE7 Websocket
我已经使用 Java EE 7 提供的 api 实现了一个 WebSocket。此外,我已经实现了一个可以毫无问题地请求我的 WebSocket 的客户端。为了确保这在执行一些代码更改时仍然有效,我想实施测试,这些测试也可以在构建服务器上进行 运行,例如Jenkins CI 不仅在本地。我正在使用 maven。
这是我的服务器端点:
import javax.enterprise.context.ApplicationScoped;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ApplicationScoped
@ServerEndpoint("/example")
public class WebSocket {
private final Set<Session> sessions = Collections.synchronizedSet(new HashSet<>());
@OnOpen
public void open(Session session) {
sessions.add(session);
}
@OnClose
public void close(Session session) {
sessions.remove(session);
}
@OnError
public void onError(Throwable error) {
//TODO do something
}
@OnMessage
public void handleMessage(String message, Session session) throws IOException {
session.getBasicRemote().sendText("Hello "+message+"!");
}
}
这是我的客户端:
import javax.websocket.*;
import java.io.IOException;
import java.net.URI;
@ClientEndpoint
public class WebsocketClient {
private String uri = "ws://localhost:8181/<some-path>/example";
private Session userSession = null;
private String answer;
public WebsocketClient() {
try {
WebSocketContainer container = ContainerProvider
.getWebSocketContainer();
container.connectToServer(this, new URI(uri));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public boolean isClosed() {
return userSession == null || !userSession.isOpen();
}
@OnOpen
public void onOpen(Session userSession) {
this.userSession = userSession;
}
@OnClose
public void onClose(Session userSession, CloseReason reason) {
this.userSession = null;
}
@OnMessage
public void onMessage(String message) {
this.answer = message;
}
public String getAnswer() {
return answer;
}
public void sendMessage(String message) {
if (userSession != null && userSession.isOpen())
try {
this.userSession.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
else {
System.out.println("Session closed!");
}
}
public void reset() {
this.answer = null;
}
}
我还有一些其他 类 在使用 CDI 的构建服务器上进行了测试。为了能够使用 CDI 和其他应用程序容器功能,我在版本 7.0.0-M3
中使用 EJBContainerRunner
和 apache TomeEE/OpenEJB 启动嵌入式 TomEE 运行s 我的测试并关闭之后它下来。使用这种方法,我没有 URL 可以调用。这适用于例如JAX-RS REST 服务,您可以在其中简单地在测试中调用 类 方法并检查响应。但是如何使用 WebSockets 做这样的事情呢?由于缺少 Session
.
,我不能简单地调用这些方法
我目前的测试是这样的:
import org.apache.openejb.junit.jee.EJBContainerRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.SocketException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
@RunWith(EJBContainerRunner.class)
public class TestWebsocket {
private WebsocketClient socket;
@Test
public void test() throws SocketException {
String answer = requestSynchronous("Java");
assertThat(answer, is(equalTo("Hello Java!")));
}
public String requestSynchronous(String message) throws SocketException {
if (socket == null || socket.isClosed()) {
socket = new WebsocketClient();
}
socket.reset();
socket.sendMessage(message);
String answer = null;
int i = 0;
while (answer == null && i < 10000) {
try {
answer = socket.getAnswer();
Thread.sleep(1);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (answer != null)
return answer;
else throw new SocketException("Connection timeout");
}
}
这有效 运行在我的本地机器上使用 TomEE,例如tomee-maven-plugin
。但是这种方法不能在构建服务器上完成。有没有比配置特殊端口或设置虚拟机进行测试更简单的方法?
提前致谢!
我找到了解决我的测试问题的方法,无需模拟,使用虚拟机,...
为了向客户端发送应答消息,不需要调用 session.getBasicRemote().sendText("...");
。相反 return 您要发送的消息。
classWebSocket
中的handleMessage
方法改为:
@OnMessage
public String handleMessage(String message){
return "Hello "+message+"!";
}
测试简化为:
@RunWith(EJBContainerRunner.class)
public class TestWebsocket {
@Inject
private WebSocket socket;
@Test
public void test() throws SocketException {
String answer = socket.handleMessage("Java");
assertThat(answer, is(equalTo("Hello Java!")));
}
}
此方法不会向为测试启动的 Web 应用程序容器外部发送消息。这使得处理测试变得更加容易。
我已经使用 Java EE 7 提供的 api 实现了一个 WebSocket。此外,我已经实现了一个可以毫无问题地请求我的 WebSocket 的客户端。为了确保这在执行一些代码更改时仍然有效,我想实施测试,这些测试也可以在构建服务器上进行 运行,例如Jenkins CI 不仅在本地。我正在使用 maven。
这是我的服务器端点:
import javax.enterprise.context.ApplicationScoped;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@ApplicationScoped
@ServerEndpoint("/example")
public class WebSocket {
private final Set<Session> sessions = Collections.synchronizedSet(new HashSet<>());
@OnOpen
public void open(Session session) {
sessions.add(session);
}
@OnClose
public void close(Session session) {
sessions.remove(session);
}
@OnError
public void onError(Throwable error) {
//TODO do something
}
@OnMessage
public void handleMessage(String message, Session session) throws IOException {
session.getBasicRemote().sendText("Hello "+message+"!");
}
}
这是我的客户端:
import javax.websocket.*;
import java.io.IOException;
import java.net.URI;
@ClientEndpoint
public class WebsocketClient {
private String uri = "ws://localhost:8181/<some-path>/example";
private Session userSession = null;
private String answer;
public WebsocketClient() {
try {
WebSocketContainer container = ContainerProvider
.getWebSocketContainer();
container.connectToServer(this, new URI(uri));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public boolean isClosed() {
return userSession == null || !userSession.isOpen();
}
@OnOpen
public void onOpen(Session userSession) {
this.userSession = userSession;
}
@OnClose
public void onClose(Session userSession, CloseReason reason) {
this.userSession = null;
}
@OnMessage
public void onMessage(String message) {
this.answer = message;
}
public String getAnswer() {
return answer;
}
public void sendMessage(String message) {
if (userSession != null && userSession.isOpen())
try {
this.userSession.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
else {
System.out.println("Session closed!");
}
}
public void reset() {
this.answer = null;
}
}
我还有一些其他 类 在使用 CDI 的构建服务器上进行了测试。为了能够使用 CDI 和其他应用程序容器功能,我在版本 7.0.0-M3
中使用 EJBContainerRunner
和 apache TomeEE/OpenEJB 启动嵌入式 TomEE 运行s 我的测试并关闭之后它下来。使用这种方法,我没有 URL 可以调用。这适用于例如JAX-RS REST 服务,您可以在其中简单地在测试中调用 类 方法并检查响应。但是如何使用 WebSockets 做这样的事情呢?由于缺少 Session
.
我目前的测试是这样的:
import org.apache.openejb.junit.jee.EJBContainerRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.net.SocketException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
@RunWith(EJBContainerRunner.class)
public class TestWebsocket {
private WebsocketClient socket;
@Test
public void test() throws SocketException {
String answer = requestSynchronous("Java");
assertThat(answer, is(equalTo("Hello Java!")));
}
public String requestSynchronous(String message) throws SocketException {
if (socket == null || socket.isClosed()) {
socket = new WebsocketClient();
}
socket.reset();
socket.sendMessage(message);
String answer = null;
int i = 0;
while (answer == null && i < 10000) {
try {
answer = socket.getAnswer();
Thread.sleep(1);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (answer != null)
return answer;
else throw new SocketException("Connection timeout");
}
}
这有效 运行在我的本地机器上使用 TomEE,例如tomee-maven-plugin
。但是这种方法不能在构建服务器上完成。有没有比配置特殊端口或设置虚拟机进行测试更简单的方法?
提前致谢!
我找到了解决我的测试问题的方法,无需模拟,使用虚拟机,...
为了向客户端发送应答消息,不需要调用 session.getBasicRemote().sendText("...");
。相反 return 您要发送的消息。
classWebSocket
中的handleMessage
方法改为:
@OnMessage
public String handleMessage(String message){
return "Hello "+message+"!";
}
测试简化为:
@RunWith(EJBContainerRunner.class)
public class TestWebsocket {
@Inject
private WebSocket socket;
@Test
public void test() throws SocketException {
String answer = socket.handleMessage("Java");
assertThat(answer, is(equalTo("Hello Java!")));
}
}
此方法不会向为测试启动的 Web 应用程序容器外部发送消息。这使得处理测试变得更加容易。