2

我开始使用一些测试驱动的开发实践,并且在决定是否以及如何测试我的这段代码时遇到问题。

我有一个AbstractServer包含ServerSocketFactoryand的类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 ...

theServerSocket和 the ServerSocketFactoryareprivate都不会暴露在这个类之外。

我的问题:

  1. 我是否应该创建测试来检查我是否真的创建了ServerSocketServerSocketFactory?他们在private课堂上并没有暴露出来 - 多少测试是太多的测试?

  2. 如果测试他们的创建是我应该做的事情,我如何从类外部测试私有的、非公开的(无 getter 方法)对象创建?我天真(阅读:未经测试)的假设是我会创建一个测试类extending AbstractServer;然后,我必须制作我正在测试的东西protected,这半挫败了制作它们private的初衷。

4

4 回答 4

1

首先,在单元测试期间不要考虑类的内部细节。对于您的单元测试,被测类是一个黑匣子。您没有关于其内部结构的信息。这就是单元测试的想法。

现在,问自己一个问题:您的课程公开的功能是什么?根据您的示例,它创建一个服务器套接字并开始监听它。现在使用单元测试作为指定此功能的手段(伪代码):

int port = 12345;
AbstractServer server = new AbstractServer(port) { };
new Socket("localhost", port);

而已。这个测试解释了你的课程是如何工作的以及它做了什么。当/如果该类停止提供该功能 - 测试将失败并指示您。这正是测试的目的。

于 2012-06-27T13:37:03.863 回答
1
  1. 我不为填充类变量编写单元测试,这太微不足道了,在我看来,不需要测试。我编写单元测试来测试例程。例如,要确保我的add()方法实际添加并且我的remove()方法实际删除(正确的对象)。如果这些类变量由于某种原因没有正确实例化,那么我的功能测试将捕捉到这一点。
  2. 至于测试private变量/类,我建议查看以下答案:https ://stackoverflow.com/a/7075965/1201423 。它背后的基本概念是:如果它是private并且你需要测试它,它真的应该是private吗?
于 2012-06-27T00:18:11.540 回答
0

首先测试抽象类不是一个好主意。您应该测试具体的实现。抽象类只是删除代码重复的一种方式(通过 IS-A 关系),您可以通过许多其他方式删除重复(例如我更喜欢的是 HAS-A 关系)。

查看您的代码和您的问题可能是这个视频: 如何编写干净、可测试的代码 它将告诉您为什么您采用的方法可能不是一个好主意,并会为您指出一些示例解决方案。

通常:指定您的班级提供的场景/功能。不要测试实现细节。

初学者的良好知识来源是:测试驱动开发博客。看看那里的旧帖子。

编辑:如果你想测试遗留代码,也有适用的模式。在这种情况下,一般规则是从验收开始,而不是单元测试。

于 2012-07-02T12:20:46.050 回答
0

您实际上并不需要专门测试这个简单的构造函数。只有两个调用 - 这两个调用都是公开可访问的方法,并且可以进行测试以确保它们能够以自己的方式工作。即使在更复杂的构造器情况下,也应该使用可测试的构造器模式。

至于多少是太多,我有时可能会稍微放松封装以使测试更容易,但这确实取决于具体情况。通常,只要您彻底测试您的公共 api,您就可以确信模块中的所有代码都正常工作 - 如果公共 api 完全工作,那么任何私有代码都应该没有问题。

这是一篇关于 tdd 的文章,涉及一些更难的领域:这里

于 2012-06-27T00:17:21.237 回答