可测试性设计
设计可测试性意味着对代码进行设计,以使其更易于测试。为此,我们可能必须打破一些我们在大学学到的原理,例如封装。
可替换的依赖
使单元更易于测试的第一件事是允许从外部设置其依赖性。因此,我们可以注入模拟依赖项而不是真实的依赖项。使用这些模拟对象,我们可以记录单元如何使用依赖关系,然后对其进行断言,以确保单元正常工作。我已经在"存根,模拟和代理测试"一文中对此进行了更详细的介绍。
将私人变成受保护的
如果方法或者字段是私有的,则只有该类的实例才能访问该方法或者字段。另一方面,同一包中的其他类也可以访问受保护的方法或者字段,并且该单元的子类也可以访问。
如果单元测试与要测试的单元位于同一软件包中(尽管仍位于不同的根目录下),则该单元测试实际上可以访问该单元的受保护方法和字段。这样可以更轻松地声明内部方法的结果以及单元的内部状态。
该方法是受保护的而不是私有的,仍然会向用户发出信号,即使我们在单元测试中这样做,也可能不是由单元的客户端直接使用的方法。
将对依赖的调用封装在受保护的方法中
通过将对外部依赖项(组件)的调用封装在受保护的方法中,可以创建要测试的单元的子类模拟,并覆盖这些受保护的方法,以使它们记录有关是否被调用的信息。
我已经在" Subclass Mocks"一文中讨论了这种技术。
将代码移出边界类
边界类有时可能很难测试。 "边界类"是指插入某个框架的类。我们可能需要运行整个框架才能测试边界类。
边界类的示例包括Servlet,Struts动作,自定义Swing组件,EJB等。这些边界类中的每一个都需要运行较大的框架或者服务器才能进行测试。
解决该问题的一种方法是将业务逻辑移出边界类,并移入其自己的组件中。然后,边界类将调用此组件。执行线程将如下所示:
boundaryClass --> business logic component --> ...
确保业务逻辑组件对边界类一无所知。例如,如果边界类是servlet,则业务逻辑类应该对HttpRequest或者HttpResponse接口一无所知。
优选地,业务逻辑类仅采用其所需的参数作为其所需的类型。例如,如果它需要在请求中发送的ID,则Servlet将把ID从请求中取出,将其转换为long,然后将其传递给业务逻辑组件。
当业务逻辑类与边界类分开时,我们可以分别测试业务逻辑类。与尝试进行单元测试(例如进行单元测试)相比,这通常更容易。 servlet或者Struts操作。最小化边界类以分发逻辑时,如果我们选择不对它们进行单元测试,则它们中出错的风险要小得多。