2008-11-11 126 views
35

我正在开发一个Spring MVC项目,并对源代码树中的所有组件进行了单元测试。单元测试与Spring的集成测试

例如,如果我有一个控制器HomeController,这需要有一个LoginService注入,然后在我的单元测试HomeControllerTest我简单地实例化对象为正常(春之外),并注入属性:

protected void setUp() throws Exception { 
    super.setUp(); 
    //... 
    controller = new HomeController(); 
    controller.setLoginService(new SimpleLoginService()); 
    //... 
} 

这很适合作为一个独立单元测试每个组件 - 除非现在我在项目中有几十个类,写了一个类并为它写了一个成功的单元测试之后,我一直忘记更新我的Spring MVC上下文文件,用于在部署的应用程序中进行实际配线。我发现当我将项目部署到Tomcat并从非布线Bean中找到一堆NullPointers时,我忘记了更新上下文文件。

所以,这里是我的问题:

  1. 这是我的第一个春天项目 - 是正常的,创造个人豆单元测试,因为我已经做了,然后创建一个测试的第二套房(集成测试)来测试一切如实际应用程序上下文一样工作?这是否有一个确定的最佳实践?

  2. 另外,如何将单元测试与集成测试分开?我有src的所有源代码,单元测试test - 是否应该有用于集成测试用例的第二个测试文件夹(如test-integration)?

因为这是我的第一个Spring项目,我很好奇别人怎样通常去这样做这样的事情 - 和而不是重新发明轮子我宁愿叫社会的其余部分。

回答

32

我不能说是最佳做法,但这是我过去所做的。

单元测试:

  • 创建非平凡豆(即大部分的春天的相关Bean)
  • 用嘲笑的注射服务的单元测试,其中实际(即大多数,如果不是全部时间)。
  • 在项目test目录中对这些测试使用标准命名约定。使用TestTestCase作为类名的前缀或后缀似乎被广泛使用。

集成测试:

  • 创建AbstractIntegrationTestCase,设置了一个SpringWebApplicationContext在intetgration测试clases使用。
  • test目录中对集成测试使用命名约定。我使用IntTestIntegrationTest作为这些测试的前缀或后缀。

设立三个蚂蚁test目标:

  1. 测试所有(或任何你想将它命名):运行单元测试和集成测试
  2. 测试:运行单元测试(只是因为test似乎是最常见的用法进行单元测试
  3. 测试集成:运行集成测试

如前所述,您可以使用对您的项目有意义的命名约定。

至于将单元从集成测试分离到一个单独的目录中,只要开发者及其工具能够轻松找到并执行它们,我认为它不重要。

作为一个例子,我和Spring一起工作的最后一个Java项目完全使用上面描述的内容,集成测试和单元测试都在同一个test目录中。另一方面,Grails项目在通用测试目录下显式地将单元和集成测试目录分开。

+1

这听起来像一个很好的策略。但是在单元测试和集成测试在同一个目录中,Eclipse没有办法让它们分开,是吗? Eclipse运行junit测试的唯一选项是运行一个或全部运行在某个文件夹中 - 不能像Ant那样通过名称来分割它们。 – 2008-11-11 19:22:38

+0

我必须回去检查Eclipse - 你是对的,如果它们在同一个目录下,我没有看到区分测试的方法。我上一个Spring项目是在Idea/Intellij中完成的,并且已经足够长,我不记得IDE配置是什么。 – 2008-11-11 22:55:10

4

很多繁琐的双簿记着春天的消失,如果你也切换到纯注释政权,在那里你注释与@Component,@Controller,@Service以及@Repository所有的豆类。只需将@Autowired添加到需要注入的属性即可。弹簧参考手册的

见第3.11节。 http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config

与此相关的,我们一直在使用的划分单元/ Integratrion测试,景描述。在我最近的制度中,我们还推出了第三个“测试类”,“ComponentTests”。这些运行时采用全弹簧布线,但采用有线存根实现(在春季使用组件扫描过滤器和注释)。

我们这样做的原因是因为对于某些“服务”层来说,最终会出现一大堆手动编码的布线逻辑来手动连接bean,有时还会有大量可笑的模拟对象。用于5行测试的100条布线并不少见。组件测试缓解了这个问题。

0

当我创建Web应用程序的集成测试,我把它们放在一个单独的目录。他们使用的是内置的JUnit或TestNG的,并使用类似Selenium命中网页,好像他们是用户测试与系统交互。该周期会是这样的:编译,运行单元测试,构建Web应用程序,将其部署到正在运行的服务器,执行测试,取消部署应用程序,并报告结果。这个想法是测试整个系统。

2

使用的InitializingBean接口(实现方法“的afterPropertiesSet”)或指定您的豆的初始化方法。 InitializingBean通常更简单,因为您不需要记住将init方法添加到bean。

使用afterPropertiesSet方法,以确保一切被注入非空,如果是空,抛出异常。

0

,相对于来自集成测试单独运行单元测试,我把所有的后者为集成测试目录,并使用IDE /蚂蚁使用像this的方法运行它们。适用于我。

6

几个孤立点:

是的,这是对弹簧试验的常用方法 - 单独的单元测试和集成测试其中前者不加载任何Spring上下文。

对于您的单元测试,可能考虑嘲笑以确保您的测试集中在一个隔离模块上。

如果你的测试是在一系列依赖关系中进行连线,那么它们并不是真正的单元测试。他们是集成测试,您使用新的而不是依赖注入来连接依赖关系。当您的生产应用程序使用Spring时,浪费时间和重复工作!

启动Spring上下文的基本集成测试很有用。

@required注释可以帮助您确保在Spring布线中捕获所需的依赖关系。

也许看看Maven会给你明确的阶段来绑定你的单元和集成测试。 Maven在Spring社区中被广泛使用。

0

单元测试和集成测试的区别是,单元测试并不一定加载情况下,你会注重你所编写的代码 - 它的工作原理失败较快时,即有和没有例外,通过嘲弄任何依赖调用它。 但是在集成测试的情况下,您可以加载上下文并执行端到端测试,如实际方案。