unit testing与Spring的集成testing
我正在开发一个Spring MVC项目,并对源代码树中的所有组件进行了unit testing。
例如,如果我有一个控制器HomeController
,需要注入一个LoginService
,那么在我的unit testingHomeControllerTest
我只是简单地实例化对象(在Spring之外)并注入属性:
protected void setUp() throws Exception { super.setUp(); //... controller = new HomeController(); controller.setLoginService( new SimpleLoginService() ); //... }
这对于testing每个组件作为一个单独的单元非常适用 – 除了现在我有几十个类在项目中,写了一个类并写了一个成功的unit testing之后,我一直忘记更新我的Spring MVC上下文文件部署应用程序中的实际接线。 我发现当我将项目部署到Tomcat并从非接线的bean中find一堆NullPointers时,我忘了更新上下文文件。
所以,这是我的问题:
-
这是我的第一个Spring项目 – 正如我所做的为单个bean创buildunit testing是正常的,然后创build第二套testing(集成testing)来testing一切与实际应用程序上下文的预期一致吗? 有没有一个确定的最佳实践呢?
-
另外,如何将unit testing和集成testing分开? 我有所有的源代码在
src
,unit testing在test
– 应该有第二个testing文件夹(如test-integration
)集成testing用例?
既然这是我的第一个春季项目,我很好奇别人通常会怎么做这样的事情 – 而不是重新发明轮子,而是问问其余的社区。
我不能说是最好的做法,但这是我过去所做的。
unit testing:
- 为非平凡的bean创buildunit testing(即,大部分Spring相关的bean)
- 在实际情况下使用Mocks进行注入服务(即,如果不是全部的话)。
- 在项目
test
目录中对这些testing使用标准的命名约定。 使用Test
或TestCase
作为类名的前缀或后缀似乎被广泛使用。
集成testing:
- 创build一个
AbstractIntegrationTestCase
,设置一个Spring
WebApplicationContext
用于整合testing类。 - 在
test
目录中使用集成testing的命名约定。 我已经使用IntTest
或IntegrationTest
作为这些testing的前缀或后缀。
设置三个Ant test
目标:
- 全部testing(或任何你想命名它):运行单位和综合testing
- testing:运行unit testing(仅仅因为
test
似乎是unit testing最常用的用法 - testing集成:运行集成testing。
如上所述,您可以使用对您的项目有意义的命名约定。
至于把单元从集成testing分离到一个单独的目录中,只要开发人员和他们的工具能够轻松地find并执行它们,我不认为这很重要。
作为一个例子,我和Spring一起工作的最后一个Java项目使用了上面所描述的,集成testing和unit testing都在同一个test
目录中。 另一方面,Grails项目在通用testing目录下明确地将单元和集成testing目录分开。
几个孤立点:
是的,这是Springtesting的常用方法 – 单独testingunit testing和集成testing,前者不加载任何Spring上下文。
对于你的unit testing,也许考虑嘲笑,以确保你的testing集中在一个孤立的模块。
如果你正在进行testing,那么他们不是真正的unit testing。 他们是集成testing,你使用新的而不是dependency injection来连接依赖关系。 当您的生产应用程序使用Spring时浪费时间和重复的工作!
基本的集成testing来调出你的Spring上下文是有用的。
@required注释可以帮助你确保你在你的Spring配线中捕获所需的依赖关系。
也许看看Maven会给你明确的阶段来绑定你的单元和集成testing。 Maven在Spring社区中被广泛使用。
如果你也切换到一个纯粹注释的政权,那么你用@Component,@Controller,@Service和@Repository注释你的所有bean,那么很多繁琐的双重保留与spring都会消失。 只需添加@Autowired到你需要注入的属性。
参见春季参考手册的第3.11节。 http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config
在相关说明中,我们一直在使用KenG描述的部门/ Integratriontesting。 在我最近的制度中,我们也引入了第三个“类别”testing,“ComponentTests”。 这些使用全弹簧布线运行,但使用有线存根实现(在春季使用组件扫描filter和注释)。
我们这样做的原因是因为对于某些“服务”层来说,最终会出现大量的手动编码布线逻辑来手工连接bean,有时还会有大量可笑的模拟对象。 5线testing的100线接线并不less见。 组件testing缓解了这个问题。
使用InitializingBean接口(实现一个方法“afterPropertiesSet”)或为bean指定一个init方法。 InitializingBean通常更简单,因为您不需要记住将init方法添加到bean中。
使用afterPropertiesSet来确保一切都被注入为非null,如果它为null,则抛出一个Exception。
当我为Web应用程序创build集成testing时,我把它们放在一个单独的目录中。 它们使用jUnit或TestNG构build,并使用Selenium等与用户相似的网页进行交互。 循环将如下所示:编译,运行unit testing,构buildWeb应用程序,将其部署到正在运行的服务器,执行testing,取消部署应用程序并报告结果。 这个想法是testing整个系统。
关于unit testing与集成testing分开运行,我把所有的unit testing放到一个集成testing目录中,并使用这种方法使用IDE / Ant来运行它们。 为我工作。
unit testing和集成testing之间的区别在于,unit testing不一定会加载你的上下文,你关注的是你编写的代码 – 它运行失败很快,也就是说,有和没有例外,嘲弄任何依赖调用。 但是在集成testing的情况下,你需要加载上下文,并像实际场景一样执行端到端的testing。