Java 如何在JUnit测试中的不同线程中启动Main.Main()

Java 如何在JUnit测试中的不同线程中启动Main.Main(),java,multithreading,sockets,junit,Java,Multithreading,Sockets,Junit,如何在Junit测试中启动运行项目主类的独立线程? 我有一个主类,它实例化了Servidor(),最终监听套接字连接,并且工作正常 以下是主要内容: public class Main { public static void main(String[] args){ try{ Servidor servidor = new Servidor(); servidor.start(); }catch(Excep

如何在Junit测试中启动运行项目主类的独立线程?

我有一个主类,它实例化了
Servidor()
,最终监听套接字连接,并且工作正常

以下是主要内容:

public class Main {
    public static void main(String[] args){
        try{
            Servidor servidor = new Servidor();
            servidor.start();
        }catch(Exception ex){
            MyUtils.handle(ex);
        }
    }
}
这里是施维多():

但是,我设计了以下Junit测试,正如预期的那样,只要我的项目在后台运行,它就可以正常工作:

public class ServidorTest {
    @Test
    public void testSendPedido() throws Exception{
        MySerializableObject pedido = new MySerializableObject();
        Socket cliente = new Socket("127.0.0.1", 2020);
        ObjectOutputStream out = new ObjectOutputStream(cliente.getOutputStream());
        out.writeObject(pedido);
    }

}
所以我想做的是能够做一些事情,比如:

    @Test
    public void testSendPedido() throws Exception{
        Main.main(); //Option1
        new Servidor().start(); //Option 2

        MySerializableObject pedido = new MySerializableObject();
        Socket cliente = new Socket("127.0.0.1", 2020);
        ObjectOutputStream out = new ObjectOutputStream(cliente.getOutputStream());
        out.writeObject(pedido);
    }

但是,这两个选项都不起作用,因为
Servidor()
劫持了执行线程,而测试永远不会通过这些行。

通过使
Servidor()
实现
Runnable
并从Junit启动不同的线程来解决这个问题。然而,我不确定Junit是否能安全地处理这些新线程。我猜只要
Servidor
没有关键状态更改,我就没事了。然而,我对更好的解决方案持开放态度

public class Servidor extends javax.swing.JPanel implements Runnable{
    ...
    public void run(){start()}
}
所以测试是这样的

@Test
public void testSendPedido() throws Exception{
    Thread thread = new Thread(new Servidor());
    thread.start();
    ...
}

要生成线程,可以使用以下方法:

final ExecutorService exService = Executors.newSingleThreadExecutor();
exService.execute(new Runnable() { // or use submit to get a Future (a result of computation, you'll need a Callable, rather than runnable then)
   public void run() {
    // do your arbitrary stuff
   }
});

// do stuff in the main thread.

// waits for termination for 30 seconds
exService.awaitTermination(30, TimeUnit.SECONDS);
exService.shutdownNow();

使用这种结构,您不必更改代码,只需将所需的内容放入
run方法中即可。请注意,它当然可以像任何java 8+代码一样与lambdas一起工作,我特意使用java 7样式向您展示了此处所涉及的接口。

这实际上非常有用,但也会使测试代码膨胀
final ExecutorService exService = Executors.newSingleThreadExecutor();
exService.execute(new Runnable() { // or use submit to get a Future (a result of computation, you'll need a Callable, rather than runnable then)
   public void run() {
    // do your arbitrary stuff
   }
});

// do stuff in the main thread.

// waits for termination for 30 seconds
exService.awaitTermination(30, TimeUnit.SECONDS);
exService.shutdownNow();