Мини-веб-сервер-макет: java.net.SocketException: сброс соединения

#java #junit

#java #junit

Вопрос:

Я создал небольшой «веб-сервер» в качестве макета для моих тестов 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 раз, чтобы заставить его работать один раз.

Комментарии:

1. Что именно вы пытаетесь здесь протестировать? Подключение сокета к веб-серверу? Или отмена сортировки потока? Вы думали о том, чтобы разбить этот фрагмент кода на отдельные более легко тестируемые классы?

2. я хочу протестировать отмену сопоставления потока. я возвращаю строку XML и хочу посмотреть, правильно ли моя программа обрабатывает ее или нет. Обычно моя программа получает этот XML-файл с реального сервера, и я хочу создать макет для этого сервера. Очень простой, который просто возвращает строку XML (одинаковую для каждого запроса).

Ответ №1:

Косвенный ответ: не пытайтесь сделать это самостоятельно. Используйте встроенный простой или причальный сервер. Примерно с тем же объемом кода вы получите относительно огромный объем функциональности, помимо того, что у вас есть, и вы также не столкнетесь с подобными странными проблемами.

«Сброс соединения» происходит потому, что вы закрываете сокет до того, как URL-соединение будет готово для этого.

Комментарии:

1. хорошо, jetty отлично работает. я думал, что настроить настоящий веб-сервер будет сложнее, но это было очень просто. спасибо.

Ответ №2:

Опубликованный вами блок кода выполняет как 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);
}
  

Теперь вы можете протестировать свой unmarshaller с любым типом InputStream. В этом случае я использовал образец XML-файла с диска.

Комментарии:

1. хороший совет. но я думаю, что мне тоже понадобится веб-сервер. программа использует его для разных функций, и макет был бы отличным.