简而言之:该代码创建一个新的ServerSocket侦听特定端口上;和当“请求”进入该端口时,它启动一个线程来处理该客户端。
与代码的问题:
- 它运行一段时间(true)循环;所以方法是不是应该会回来的
- 而且,除此之外,它写在很难测试的方式;基本上是因为你在那个方法中有两个对
new
的调用。
我将解释你是怎么克服的第二部分;然后让我们谈谈第一点。关于“测试”本身,您有两种选择:
- 锁定PowerMock(丑陋);或者Mockito间谍可能会帮助;到模拟那些调用新的。 (Mockito可以,但PowerMock并不在我眼里)
- 首选:将您的代码更改为易于测试;然后使用依赖注入。
像:
public class Server {
private final SocketFactory socketFactory;
private final ThreadFactory threadFactory;
public Server() {
this(new SocketFactory(), new ThreadFactory());
}
Server(SocketFactory socketFactory, ...
this.socketFactory = socketFactory...
public void startServer() throws IOException
{
ServerSocket ss = socketFactory.createSocketFor(portNum);
while(true)
{
Socket s = ss.accept();
Thread t = threadFactory.newThreadFor(new ConnectionHandler(s));
t.start();
}
}
而现在......一切都超级简单:你可以使用第二包装保护的构造函数来插入嘲笑工厂;然后您可以配置/验证这些工厂看到您期望的呼叫。
当然,这可能看起来像“更多”的工作;因为现在你必须创建这两个其他类(实际上你可以使用接口加IMPL类)。但事情是:你最终得到更好的设计,这不仅更容易测试,而且更容易维护和提高。
然后:创建“裸机”线程不再是一个好的做法。 (特别是不在while-true循环中;如果你还在搜索你的bug)你应该看看一些ThreadPool类;确保你是不是不断创建新线程。那些是“昂贵的”;你应该非常喜欢“重用”线程。还有一些图书馆可以帮助你!
行,回到其他问题:截至目前,你根本无法合理 单位由于while(真)的测试此方法。你看,当你模拟那ServerSocket,那么调用accept()将不会阻塞;你遇到了一些无限循环,创建了模拟线程。因此:你必须重新编写这段代码(以允许在外部停止它)......或者你可以设置ThreadFactory模拟来返回一个嘲讽线程;或者你可以设置ThreadFactory模拟来返回一个模拟线程。抛出一些特定的异常。然后你的单元测试只是期望抛出异常 - 作为你预期的事情发生的间接“证明”。
一个'while(true)'循环很难测试,因为测试永远不会结束(如果你不能在while(true)-loop内部调用一个exeption)。 ;-) –
以防万一您觉得愿意接受我的回答;如果明天你可以考虑这样做会很好......因为我已经达到了日常上限;-) – GhostCat