现在,你可以基于前面概括的五个步骤继续编写行为测试。下面的代码展示了相应于SimpleActionTest的部分代码,步骤已在注释中标出。
使用MockStrutsTestCase和EasyMock进行行为测试的部分代码:
在行动及其依赖的服务之间存在四种可能的复合关系:
每个行为依赖于一个服务。
每个行为依赖于多个服务。
多个行为依赖于一个服务。
多个行为依赖于多个服务。
我在此展示的方案能够比较灵活而且相对容易地支持上面所有这四种情形,因为模拟创建、期望值建立以及模拟注入都能够在单个的测试类内实现。
你能够不借助于监听器接口就可以在StrutsActionPreExecuteNotifier内部模拟注入吗?这看起来似乎使得测试类实现更简单一些。然而,实践证明,类似早些时候讨论的OOP方案,编写多个方面以创建不同的模拟对象并建立相应的不同的模拟期望是非常必要的。另外,在单个测试类内本地化模拟的创建与安装(借助于监听技术,这是可能的)将变得更为方便。
五、总结
对于我们在本文中所讨论的集成问题,有人可能会创造出一套相当不错的OOP方案。然而,构造这种方案很可能需要对Struts和StrutsTestCase有深入的理解才行,并且要付出相当的努力。影响本文中所讨论的两个测试框架(StrutsTestCase和EasyMock)紧密集成的主要障碍在于,在Struts行为实例执行之前很难实现对它的访问。在认识了导致这种障碍的基本原因之后,AOP方案自然地出现在我们面前。不必再强求于基于传统型OOP的那种更复杂的方案,AOP允许我们把我们的方案更为紧密地映射到问题空间。
其实,AOP的真正“魔术”在于它的连接点模型,它能够使你“穿越”中间对象(例如ActionServlet和RequestProcessor)进而直指问题的核心。借助于AOP技术中确定横切关注点这种非常“节俭”的方法,开发者即能够设计出非常直观而且更为简单的解决方案。AOP,这种强有力的编程方法正好弥补了传统型OOP编程中所存在的不足。如果被恰当用于解决适当类型的问题,那么,AOP有助于改进代码的模块化,最终会产生出更为清晰和更易于理解的代码。最后,非常希望本文不仅有助于你的Struts应用程序的单元测试,而且还吸引你进一步探讨AOP编程所体现出来的其它重要优点。