【问题标题】:How To Perform JUnit Testing on Socket and OutputStreamWriter如何对 Socket 和 OutputStreamWriter 执行 JUnit 测试
【发布时间】:2020-12-27 13:03:58
【问题描述】:

想就我的单元测试如何关闭套接字和 outputstreamwriter 的方法寻求帮助。目前,我的单元测试能够覆盖的只是抛出异常的部分。

方法如下:

private final void CloseConnection() {
    ErrorHandler objErrHdl = new ErrorHandler();

    try {
        out.close();
        clientSocket.close();
    } catch ( IOException e ) {
        objErrHdl.LogError( this.getClass().getName() , "CloseConnection" , "FAILED TO CLOSE CONNECTION" ,
                            e.toString() );
    } catch ( Exception e ) {
        objErrHdl.LogError( this.getClass().getName() , "CloseConnection" , "FAILED TO CLOSE CONNECTION" ,
                            e.toString() );
    }
}

这是我的单元测试:

        @Test
    public void testCloseConnection() throws IOException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    serverSocket = new ServerSocket(6668);
    Method method = Systematic.class.getDeclaredMethod("CloseConnection");
        method.setAccessible(true);
        method.invoke(systematic);
        clientSocket = new Socket("127.0.0.1", 6668);
        clientSocket.close(); 
        out.close(); 
    }

    @Test
    public void testCloseConnectionException() throws NoSuchMethodException, SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException, IOException {
        Method method = Systematic.class.getDeclaredMethod("CloseConnection");
        method.setAccessible(true);
        method.invoke(systematic);

        clientSocket = new Socket("0", 33654);
    }

    @Test
    public void testCloseConnectionIOException() throws NoSuchMethodException, SecurityException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {

        Method method = Systematic.class.getDeclaredMethod("CloseConnection");
        method.setAccessible(true);
        Socket s =  (Socket) method.invoke(systematic);
        Mockito.when(s).thenThrow(new IOException());
    }

正如我所说,我的单元测试的 testCloseConnectionException 是唯一成功覆盖了我正在测试的 CloseConnection 方法的一部分。谢谢。

【问题讨论】:

  • 你能说明如何在包含方法 CloseConnection 的类中设置/创建字段和 clientSocket 吗?在通过反射调用私有方法之前,我也看不到如何从测试中传递该字段的值。
  • 变量设置如下:private Socket clientSocket = null; private OutputStreamWriter out = null;
  • 我用来覆盖捕获异常部分的代码是这样的:@Test public void testCloseConnectionThrowsException() { serverSocket = new ServerSocket(6668); Method method = Systematic.class.getDeclaredMethod("CloseConnection"); method.setAccessible(true); method.invoke(systematic); clientSocket = new Socket("127.0.0.1", 6668); clientSocket.close(); out.close();}

标签: java sockets junit mockito ioexception


【解决方案1】:

我猜您在业务代码和测试中使用的对象 clientSocket 和 out 不同。

在测试中您创建新对象,但这些对象不会传播到被测类。

所以这是我对你的测试的提议:

正在测试的类,类似于您的:

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class SomeClass {

    private OutputStreamWriter out = null;
    private Socket clientSocket = null;

    private final void CloseConnection() {

        try {
            out.close();
            clientSocket.close();
        } catch (IOException e) {
            System.out.println(e);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

并对其进行测试

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;
import java.net.Socket;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {

    @Mock
    private OutputStreamWriter out;

    @Mock
    private Socket clientSocket;

    @InjectMocks
    private SomeClass someClass;

    @Test
    public void testCloseConnection() throws Exception {

        // run test method
        Method method = SomeClass.class.getDeclaredMethod("CloseConnection");
        method.setAccessible(true);
        method.invoke(someClass);

        // verify if action was taken
        Mockito.verify(clientSocket).close();
        Mockito.verify(out).close();

        // and nothing else was not occurred
        Mockito.verifyNoMoreInteractions(clientSocket, out);
    }

    @Test
    public void testCloseConnectionIOException1() throws Exception {

        // throw Exception on out.close()
        Mockito.doThrow(new IOException()).when(out).close();

        // run test method
        Method method = SomeClass.class.getDeclaredMethod("CloseConnection");
        method.setAccessible(true);
        method.invoke(someClass);

        // out.close() was called
        Mockito.verify(out).close();
        // and nothing else on out
        Mockito.verifyNoMoreInteractions(out);

        // no call on clientSocket - because out.close() throw Exception
        Mockito.verifyNoInteractions(clientSocket);
    }
}

在测试中我们可以模拟java io 类,没有必要再次测试那些。我们想针对现实世界的某些场景测试我们的应用程序和行为。

【讨论】:

  • 您好,感谢您抽出时间解决我的测试问题。显然,使用您的代码并没有涵盖该方法的 catch IOException 部分。这是唯一让我无法通过的部分,但是 JUnit 已经涵盖了 try 和 Exception 部分。
  • 感谢您的帮助,我现在能够涵盖整个 CloseConnection 方法。我刚刚在我的另一个测试用例中实例化了 SomeClass,它成功了。
猜你喜欢
  • 1970-01-01
  • 2013-07-22
  • 2020-05-25
  • 2018-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多