2016-04-23 32 views
6

我已經使用Java EE 7提供的api實現了一個WebSocket。此外,我已經實現了一個請求我的WebSocket沒有任何問題的客戶端。爲了確保在執行一些代碼更改時仍然有效,我想實現也可以在構建服務器上運行的測試,例如, Jenkins CI不僅在當地。我正在使用maven。如何測試Java EE7 Websocket

這裏是我的服務器端點:

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和其他應用程序容器功能,我使用EJBContainerRunner與Apache TomeEE/OpenEJB版本7.0.0-M3,它啓動嵌入式TomEE運行我的測試,然後關閉它。使用這種方法我沒有可以調用的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。但是這種方法無法在構建服務器上完成。有沒有比配置特殊端口或設置虛擬機進行測試更簡單的方法?

在此先感謝!

回答

6

我發現我的測試問題的解決方案,而不嘲諷,使用虛擬機,...

用於發送應答消息不需要它來調用session.getBasicRemote().sendText("...");客戶端。而是返回你想發送的消息。

類中的方法handleMessage變化WebSocket到:

@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應用程序容器之外的開始進行測試。這使得處理測試變得更容易。