Designing a test for socket creation, TDD Java
我开始使用一些测试驱动的开发实践,我在决定是否以及如何测试我的代码时遇到问题。
我有一个包含
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 ... |
我的问题:
我应该创建测试来检查我是否真的创建
如果测试他们的创建是我应该做的,我如何从类外部测试私有的,非暴露的(没有getter方法)对象创建? 我的天真(读:未经测试)假设是我创建了一个测试类
首先,在单元测试期间不要考虑类的内部细节。对于您的单元测试,正在测试的类是一个黑盒子。您没有关于其内部结构的信息。这就是单元测试的想法。
现在,问问自己一个问题:你的课程所面临的功能是什么?根据您的示例,它创建一个服务器套接字并开始监听它。现在使用单元测试作为指定此功能的方法(伪代码):
1 2 3 | int port = 12345; AbstractServer server = new AbstractServer(port) { }; new Socket("localhost", port); |
而已。该测试解释了您的课程如何运作以及它的作用。当/如果类停止提供该功能时 - 测试将失败并指示您。这正是测试的目的。
首先测试抽象类不是一个好主意。您应该测试具体的实现。抽象类只是一种删除代码重复的方法(通过IS-A关系),你可以通过许多其他方式删除重复(例如我喜欢的是HAS-A关系)。
查看您的代码和您的问题可能是您的好视频:
如何编写干净,可测试的代码。
它会告诉你为什么你采取的方法可能不是一个好主意,并会指出一些示例解决方案。
通常:指定您提供的场景/功能。不要测试实现细节。
初学者的良好知识来源是:测试驱动开发博客。看看那里的旧帖子。
编辑:
如果您想测试遗留代码,那么还有一些模式。在这种情况下,一般规则是从接受开始,而不是单元测试。
您并不需要专门测试这个简单的构造函数。只有两个调用 - 这两个调用都是可公开访问的方法,可以进行测试以确保它们能够自行运行。即使在更复杂的构造函数情况下,也应该使用可测试的构建器模式。
至于多少太多,我有时可能最终放松一点封装以使测试更容易,但这实际上取决于情况。通常,只要您彻底测试公共API,您就可以确信模块中的所有代码都正常工作 - 如果公共API完全正常工作,那么任何私有代码都应该没有问题。
这里有一些关于tdd的文章,在一些更难以涵盖的领域:这里