我开始使用一些测试驱动的开发实践,并且我在确定是否以及如何测试我的代码时遇到问题。
我的课程AbstractServer
包含ServerSocketFactory
和ServerSocket
:
public abstract class AbstractServer extends Thread {
...SNIP...
//ServerSocket and factory.
private ServerSocket ss;
private ServerSocketFactory ssf;
public AbstractServer ( int _port ) {
this.port = _port;
try {
ssf = ServerSocketFactory.getDefault();
ss = ssf.createServerSocket(port);
} catch (IOException e) {
// Couldn't create ServerSocket, die.
System.exit(1);
}
}
... SNIP ...
ServerSocket
和ServerSocketFactory
都是private
,并且永远不会在此类之外公开。
我的问题:
我是否应该创建测试以检查是否实际创建了ServerSocket
和ServerSocketFactory
?它们是private
并且没有在课堂上暴露 - 测试的测试太多了多少?
如果测试他们的创建是我应该做的,我该如何从类外部测试私有的,非暴露的(没有getter方法)对象创建?我的天真(阅读:未经测试)假设是我创建了一个测试类extending
AbstractServer
;然后,我必须制作我正在测试protected
的内容,这样做会使得private
开始的目的失败。
答案 0 :(得分:1)
add()
方法实际添加并且我的remove()
方法实际上删除了(正确的对象)。如果这些类变量出于某种原因而没有正确实例化,那么我的功能测试就会发现这一点。private
变量/类,我建议查看以下答案:https://stackoverflow.com/a/7075965/1201423。它背后的基本概念是:如果它是private
并且你需要测试它,它真的应该是private
吗? 答案 1 :(得分:1)
首先,在单元测试期间不要考虑类的内部细节。对于您的单元测试,正在测试的类是一个黑盒子。您没有关于其内部结构的信息。这就是单元测试的想法。
现在,问问自己一个问题:您的课程所面临的功能是什么?根据您的示例,它创建一个服务器套接字并开始监听它。现在使用单元测试作为指定此功能的方法(伪代码):
int port = 12345;
AbstractServer server = new AbstractServer(port) { };
new Socket("localhost", port);
就是这样。该测试解释了您的课程如何运作以及它的作用。当/如果类停止提供该功能时 - 测试将失败并指示您。这正是测试的目的。
答案 2 :(得分:0)
您并不需要专门测试这个简单的构造函数。只有两个调用 - 这两个调用都是可公开访问的方法,可以进行测试以确保它们能够自行运行。即使在更复杂的构造函数情况下,也应使用可测试的构建器模式。
至于多少太多,我有时可能最终放松一点封装以使测试更容易,但这实际上取决于具体情况。通常,只要您彻底测试您的公共API,您就可以确信模块中的所有代码都正常工作 - 如果公共API完全正常工作,那么任何私有代码都应该没有问题。 / p>
以下是一些关于tdd的优秀文章,涉及的范围更为严格:here
答案 3 :(得分:0)
首先,测试抽象类不是一个好主意。您应该测试具体的实现。抽象类只是一种删除代码重复的方法(通过IS-A关系),你可以通过许多其他方式删除重复(例如我喜欢的是HAS-A关系)。
查看您的代码和您的问题可能是您的好视频: How to Write Clean, Testable Code 强> 它会告诉你为什么你采取的方法可能不是一个好主意,并会指出一些示例解决方案。
通常:指定您提供的场景/功能。不要测试实现细节。
初学者的良好知识来源也是:Test Driven Development Blog。看看那里的旧帖子。
编辑: 如果您想测试遗留代码,那么还有一些模式。在这种情况下,一般规则是从接受开始,而不是单元测试。