Mini-Webserver-Mock:java.net.SocketException:连接重置

时间:2011-10-14 19:43:10

标签: java junit

我做了一个小的“webserver”作为我的JUnit测试的模拟。这是“网络服务器”的代码:

while(true) {

    try {
        ServerSocket socket = new ServerSocket(port);
        socket.setReuseAddress(true);
        Socket remote = s.accept();
        PrintWriter out = new PrintWriter(remote.getOutputStream(), true);
        out.append("some data");
        out.flush();
        out.close();    
        remote.close(); 
        socket.close();
    }
    catch (IOException e) { 
        throw new RuntimeException(e);
    }

这就是我在程序代码中所做的事情:

    URL url = new URL(urlstr);  
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.connect();
    MyClass myClass = (MyClass) unmarshaller.unmarshal(con.getInputStream());
    con.disconnect();
    return myClass;

这里是我的问题:有时它有效,有时不行。我不知道为什么。我收到这个错误:

java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:180)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:230)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:270)
at java.io.BufferedInputStream.read(BufferedInputStream.java:329)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:688)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:653)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1067)
at my.program.Program.myMethod(...)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.junit.runners.Suite.runChild(Suite.java:115)
at org.junit.runners.Suite.runChild(Suite.java:23)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

为什么它有时会起作用?为什么有时不呢?怎么了?我必须运行我的junit测试5或10次以使其工作一次。

2 个答案:

答案 0 :(得分:2)

间接答案:不要试图自己动手。使用嵌入式SimpleJetty服务器。使用大致相同数量的代码,您将获得超出您所拥有的相对大量的功能,并且您也不会遇到类似这样的奇怪问题。

发生了“连接重置”,因为您在网址连接准备就绪之前关闭了套接字。

答案 1 :(得分:1)

您发布的代码块同时执行HTTP连接和响应的解组。当关注点良好分离时,单元测试效果最佳。这意味着为连接和解组逻辑创建单独的类。完成此操作后,您可以使用以下代码测试解组:

class Unmarshaller {
  public MyClass unmarshal(InputStream is) {
    return (MyClass) unmarshaller.unmarsal(is);
  }
}

class UnmarshallerTests {
  @Test
  public void testUnmarshal() {
    Unmarshaller u = new Unmarshaller();
    FileInputStream fis = new FileInputStream("test-sample.xml");
    u.unmarshal(fis);
}

您现在可以使用任何类型的InputStream测试您的unmarshaller。在这种情况下,我使用了磁盘中的示例XML文件。